Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 在什么情况下,self-type注释提供扩展不可能的行为_Scala_Extends_Self Type_Cake Pattern - Fatal编程技术网

Scala 在什么情况下,self-type注释提供扩展不可能的行为

Scala 在什么情况下,self-type注释提供扩展不可能的行为,scala,extends,self-type,cake-pattern,Scala,Extends,Self Type,Cake Pattern,我试图提出一个合成场景,其中self-type和extends的行为不同,但到目前为止还没有找到。基本示例总是讨论self类型,它不要求类/特征不必是依赖类型的子类型,但即使在这种情况下,self类型和extends之间的行为似乎是相同的 trait Fooable { def X: String } trait Bar1 { self: Fooable => def Y = X + "-bar" } trait Bar2 extends Fooable { def Y = X +

我试图提出一个合成场景,其中self-type和extends的行为不同,但到目前为止还没有找到。基本示例总是讨论self类型,它不要求类/特征不必是依赖类型的子类型,但即使在这种情况下,self类型和extends之间的行为似乎是相同的

trait Fooable { def X: String }
trait Bar1 { self: Fooable =>
  def Y = X + "-bar"
}
trait Bar2 extends Fooable {
  def Y = X + "-bar"
}
trait Foo extends Fooable {
  def X = "foo"
}
val b1 = new Bar1 with Foo
val b2 = new Bar2 with Foo
是否存在这样一种情况,即当使用一种或另一种组合对象时,组合对象的某种形式或功能是不同的

更新1:感谢您提供的示例,这些示例说明了如果不进行自键入,就不可能完成。我很感谢您提供的信息,但我确实在寻找可以进行自键入和扩展,但不能互换的合成


更新2:我想我有一个特别的问题,那就是为什么各种蛋糕模式的例子通常都说必须使用self-type而不是extends。我还没有找到一个蛋糕模式场景,它不能与extends一起工作

循环引用可以使用self类型,但不能使用extends:

// Legal
trait A { self: B => }
trait B { self: A => }

// Illegal
trait C extends D
trait D extends C
当存在循环依赖项时,我有时会使用它来跨多个文件拆分实现。

scala> trait A { def a: String ; def s = "A" }
defined trait A

scala> trait B { _: A => def s = "B" + a }
defined trait B

scala> trait C extends A { def a = "c" ; override def s = "C" }
defined trait C

scala> new C {}.s
res0: String = C

scala> new A with B { def a = "ab" }.s
<console>:10: error: <$anon: A with B> inherits conflicting members:
  method s in trait A of type => String  and
  method s in trait B of type => String
(Note: this can be resolved by declaring an override in <$anon: A with B>.)
              new A with B { def a = "ab" }.s
                  ^

scala> new A with B { def a = "ab" ; override def s = super[B].s }.s
res2: String = Bab
scala>trait A{def A:String;def s=“A”}
定义特征A
scala>trait B{{{uu:A=>def s=“B”+A}
定义性状B
scala>trait C扩展了{def A=“C”;覆盖def s=“C”}
定义性状C
scala>新的C{}.s
res0:String=C
scala>使用B{defa=“ab”}.s的新A
:10:错误:继承冲突成员:
类型=>String的特性A中的方法s
类型=>String的特性B中的方法s
(注意:这可以通过在中声明重写来解决。)
带B{defa=“ab”}.s的新A
^
scala>newa与B{defa=“ab”;重写defs=super[B].s}.s
res2:String=Bab
如果有的话,关键是B.s不会覆盖A.s


这并不像另一个答案那样令人激动。

泛型参数必须是类型本身:

trait Gen[T] {self : T => ...}
我不明白如何在java或C中获得这种约束。然而,它可以近似为

trait Gen[T] {
   def asT : T // abstract
}
而且

至于自我类型,它需要融入一种特质。它不能使用类或对象。奇怪的是,它允许定义可以与混合,但只有在尝试实例化它时,它才无法编译。见这个问题:


最大的区别在于最终的公共界面。让我们以您给出的示例为例(稍微简化):

因此,如果您希望使用某个特性的功能,而不必让客户知道您正在混合该特性,那么您应该使用self-type注释

自类型批注不公开基础类型的公共接口。
扩展另一个类型总是会暴露父类型的公共接口。

奇怪的是,
\uuu:A=>
this:A=>
?@megri显然意味着同样的事情
trait B{{u=>def B=42;class C{def C=`.B}
我发现了另一件事,你可以对self类型做,而对extends做不到:self类型可以是结构类型可能的重复
trait Fooable { def foo: String = "foo" }
trait Bar1 { self: Fooable =>
  def Y = foo + "-bar"
}
trait Bar2 extends Fooable {
  def Y = foo + "-bar"
}
// If we let type inference do its thing we would also have foo() in the public interface of b1, but we can choose to hide it
def b1:Bar1 = new Bar1 with Fooable
// b2 will always have the type members from Bar2 and Fooable
def b2:Bar2 = new Bar2{}

// Doesn't compile - 'foo' definition is only visible inside the definition of Bar1
println(b1.foo)
// Compiles - 'foo' definition is visible outside the definition of Bar2
println(b2.foo)