在java世界中(更确切地说,如果你没有多重继承/ mixins),经验法则很简单:"赞成对象组合而不是类继承".
如果你还考虑mixins,我想知道它是否/如何改变,特别是在scala中?
mixins被认为是多重继承的方式,还是更多的类组合?
是否还有一个"赞成对象组成超类组成"(或其他方式)指南?
当人们使用(或滥用)mixins时,我已经看到了一些例子,当对象组合也可以完成这项工作时,我并不总是确定哪一个更好.在我看来,你可以用它们实现非常相似的东西,但也有一些差异,一些例子:
我知道简短的回答是"它取决于",但可能有一些典型的情况,当这个或那个更好.
到目前为止,我可以提出一些指导原则(假设我有两个特征A和B,A想要使用B中的一些方法):
在很多情况下,mixins似乎更容易(和/或更简洁),但我很确定它们也有一些陷阱,比如"神级"和其他两篇artima文章中描述的其他:第1 部分,第2部分(BTW it在我看来,大多数其他问题与scala不相关/不那么严重.
你有更多这样的提示吗?
我想要实现的是正确实施
def dynamix[A, B](a: A): A with B
Run Code Online (Sandbox Code Playgroud)
我可能知道B是什么,但不知道A是什么(但如果B有自我类型,那么我可以在A上添加一些约束).scala编译器对上面的签名很满意,但我还不知道实现的样子 - 如果可能的话.
我想到了一些选择:
你有其他可能有用的想法吗?你会推荐哪种方式?期待什么样的"挑战"?
或者我应该忘记它,因为目前的Scala限制是不可能的?
我的问题背后的意图:说我有一个业务工作流程,但它不是太严格.一些步骤具有固定顺序,但其他步骤没有,但最后必须完成所有步骤(或者其中一些步骤需要进一步处理).
更具体的例子:我有一个A,我可以添加B和C. 我不在乎先做哪个,但最后我需要A带B和C.
评论:我对Groovy不太了解,但是我想出了这个问题,我想这或多或少与我想要的一样,至少在构思上.
我理解编码到接口的原理 - 将实现与接口分离,并允许交换接口的实现.
我应该编写我编写的每个类的接口代码还是过度杀伤?我不想将项目中的源文件数量增加一倍,除非它确实值得.
我可以使用哪些因素来决定是否按接口编码?
说我有以下特征:
trait A
trait B { this: A => }
trait C extends B // { this: A => }
Run Code Online (Sandbox Code Playgroud)
编译器错误:illegal inheritance; self-type C does not conform to B's selftype B with A
如果我取消注释自我类型注释,编译器很高兴.
我认为很明显为什么C也需要这种自我类型.我不明白为什么它不能从A"继承"它,如果编译器已经知道它需要它?
我认为当你使用具有复杂层次结构的自我类型时,它可以减少冗长,特别是如果你混合了大量的特征,每个特征都有自己的自我类型.
我想可能有一个很好的理由当前的行为,我只是找不到/弄清楚它是什么.
起初我认为它可能与mixin线性化有关,但在我看来它并没有在这里发挥(即使我有更多的特征与更复杂的自我类型混合).
在某些情况下会引起歧义吗?如果是这样,为什么在没有歧义的情况下它不能起作用?
或者它与正确实施它的一些困难有关?
我可以找到关于这个主题的一些讨论(比如自我类型不是继承的),但是他们大多只是陈述问题并得出结论是没有太多解释和/或解决方案(如果存在)的情况.
我的Web应用程序将从外部系统触发.它将调用我的应用程序的一个请求路径,但对不同类型的请求使用不同的查询参数.
其中一个参数是"动作",它定义了要做的事情.其余的参数取决于"行动".
所以我可以得到这样的请求参数:
action=sayHello&user=Joe
action=newUser&name=Joe&address=xxx
action=resetPassword
...
Run Code Online (Sandbox Code Playgroud)
我希望能够在路由文件中对其进行类似的编码以进行播放,因此它可以执行基于查询参数的路由以及尽可能多的其他参数验证.
我所拥有的是具有大量可选参数的所有这些可能性的路由.处理它的动作以大模式匹配开始,以进行调度和参数验证.
谷歌搜索和检查SO只是弹出了大量的样本,其中params以某种方式编码在请求路径中,因此多个路径被路由到相同的操作,但我想反过来:一个路径路由到不同的操作.
我的一位同事说我们可以有一个"调度程序"动作,只根据"动作"参数重定向.它会比当前的解决方案更具结构性,但它不会消除应该有选择地传递给下一个动作的可选参数的长列表,所以我希望有人知道一个更好的解决方案:-)
BTW调用我的应用程序的外部系统是由另一家公司开发的,我对此设计没有任何影响,因此不能改变我的应用程序触发方式.
当我想使用隐式方法将函数转换为其他函数时,我遇到了一些问题.
我正在Scala 2.8中实现一个小型DSL用于测试目的.它应该支持实例上的各种检查(断言,如果你喜欢).整个DSL有点复杂,但下面的简化示例显示了我的问题:
object PimpMyFunction {
class A(val b: Int)
def b(a: A) = a.b
class ZeroCheck(f: A => Int) {
def isZeroIn(a: A) = f(a) == 0
}
implicit def fToCheck(f: A => Int): ZeroCheck = new ZeroCheck(f)
def main(args: Array[String]) {
val a0 = new A(0)
val a1 = new A(1)
println(fToCheck(b).isZeroIn(a0))
println(fToCheck(b).isZeroIn(a1))
println(b.isZeroIn(a0))
}
}
Run Code Online (Sandbox Code Playgroud)
前两个的println线(当我明确地调用转换方法)编制,做工精细,但最后一个(当我想依靠implicits)产生错误:
Compile error: missing arguments for method b in object PimpMyFunction; follow this method with '_' if you …
scala ×5
mixins ×3
composition ×1
implicit ×1
inheritance ×1
interface ×1
java ×1
oop ×1
scala-2.8 ×1
self-type ×1