相关疑难解决方法(0)

scala:重用子类实现作为两个不同类的子类?

为了简化我的实际代码,我们假设有两个类,一个是另一个的子类:

class Chair {
   val canFold = false;
   // ...
}

class FoldableChair extends Chair {
   val canFold = true;
   // ...
} 
Run Code Online (Sandbox Code Playgroud)

在我的实现中,我将有数百个其他子类的Chair或FoldableChair:

class Armchair extends ... {}
class DeckChair extends ... {} 
//... etc
Run Code Online (Sandbox Code Playgroud)

对于这些子类中的每一个,假设每个子类都有一个冗长的实现,但我希望能够让它有时扩展Chair并有时扩展FoldableChair - 而不需要复制代码.我想在没有子类本身扩展的情况下这样做.这有可能吗?我需要使用特征来做到这一点吗?

我还希望能够创建子类的特定实例,有时会扩展Chair并有时扩展FoldableChair,但是在实例化时会做出这种选择.这也可能吗?谢谢!

编辑:澄清一下,我真正想要的是:

class Armchair extends Chair {}

class ArmchairFoldable extends FoldableChair {}
Run Code Online (Sandbox Code Playgroud)

但Armchair和ArmchairFoldable的实施完全相同.也就是说,我不想复制他们的实现.

class-design scala traits

3
推荐指数
1
解决办法
212
查看次数

定义多个特征的最佳实践,这些特征为实现特定特征的类添加行为

假设我有一些traits,每个都为扩展的类添加一些行为Actor.

它们每个都需要一小部分方法Actor.他们都可以Actor像这样延伸吗?

trait A extends Actor {
  def doAThing = { ... }
}
trait B extends Actor {
  def doBThing = { ... }
}
trait C extends Actor {
  def doCThing = { ... }
}

class D extends Actor with A with B with C
Run Code Online (Sandbox Code Playgroud)

或者每个特征是否应该从Actor抽象方法中定义它所需的方法,以便它们由最终的具体类提供,这是唯一一个将扩展的类Actor

scala traits

3
推荐指数
1
解决办法
191
查看次数

为什么Scala特征不允许构造函数参数?

我是Scala的新手,来自Java,我只是在阅读有关特征的内容.经常提到的一件事是特征不会(不能?不会?)具有构造函数参数.我很想知道这是否有原因.

来自很久以前的数学/计算机科学背景,我想知道这是否是一个不可避免的后果,因为一些语言设计决定,或者是否有意识地决定避免一些继承/混合问题或其他?

希望有人知道,因为事实背后可能会有一些有趣的东西.

scala

3
推荐指数
2
解决办法
2879
查看次数

使用泛型实现Scala特征的类型

基本上,我正在尝试执行以下操作:

trait Foo[T] extends T {
  def json: Writes[T]
  def bar: String = {
    Json.toJson[T](this)(json).toString
  }
}
Run Code Online (Sandbox Code Playgroud)

我希望编译器强制使用trait Foo的任何类都是T类.不幸的是,'extends T'无效.现在,我能做的最好的事情如下:

trait Foo[T] extends T {
  def json: Writes[T]
  def bar: String = {
    Json.toJson(this.asInstanceOf[T])(json).toString
  }
}
Run Code Online (Sandbox Code Playgroud)

但显然,编译器没有强制执行任何操作.反正有没有实现我想要的?

generics scala traits

3
推荐指数
1
解决办法
93
查看次数

为什么 scala self 类型不是其要求的子类型

我想知道以下行为背后的原因是什么?

@ trait Bar
defined trait Bar

@ trait Foo { self: Bar => }
defined trait Foo

@ def x: Foo = ???
defined function x

@ val y: Bar = x
cmd3.sc:1: type mismatch;
 found   : ammonite.$sess.cmd1.Foo
 required: ammonite.$sess.cmd0.Bar
val y: Bar = x
             ^
Compilation Failed
Run Code Online (Sandbox Code Playgroud)

AFAIU,Foo要求其每个子类型都是 的子类型,Bar那么为什么实例Foo不是 的正确实例Bar

@编辑

只是为了让问题更清楚:我想知道为什么它会这样工作。一些可能的答案是:

  1. 有一些特征 X 在它们之间的子类型关系中是不可能的。
  2. 发生子类型关系是不正确的(例如,存在这样的类型实例,Foo而不是Bar运行时类型的实例)
  3. 这两种情况(有和没有子类型关系)都是有效的,因此编译器团队必须选择其中之一。如果是这样,是否有理由做出这样的决定还是随机选择?

似乎至少 1) 有点正确(隐藏子类型作为实现细节)。

inheritance scala self-type subtyping

3
推荐指数
1
解决办法
275
查看次数

覆盖特质和自我类型

我想覆盖ScalaTest特性BeforeAndAfterEach,以便为我的所有测试实现一次.最后我得到它编译,但我不明白为什么.

trait MySetup extends BeforeAndAfterEach {
  this : org.scalatest.BeforeAndAfterEach with org.scalatest.Suite =>
  var service: String = _

  abstract override def beforeEach(): Unit = {
    service = "apa"
    super.beforeEach()
  }

  abstract override def afterEach(): Unit = {
    service = ""
  }
}
Run Code Online (Sandbox Code Playgroud)

让它运作的是线:

  this : org.scalatest.BeforeAndAfterEach with org.scalatest.Suite =>
Run Code Online (Sandbox Code Playgroud)

我在BeforeAndAfterEach实现的开头找到它并复制它.

它做了什么,为什么需要它?

更新:

这是一个更简单的版本.

trait MySetup extends FlatSpec with BeforeAndAfterEach {
  var service: String = _

  override def beforeEach {
    service = "apa"
    super.beforeEach
  }

  override def afterEach {
    service = "" …
Run Code Online (Sandbox Code Playgroud)

scala traits self-type scalatest

2
推荐指数
1
解决办法
1155
查看次数

类Foo {this:SomeTraitType =>是什么意思?

我有这个基于Akka Concurrency预打印的问题(最终版本还没有),使用它时没有解释.

在课程的第1版中,他们有:

class Altimeter extends Actor with ActorLogging with EventSource{
...
}
Run Code Online (Sandbox Code Playgroud)

声称Altimeter现在与EventSource紧密结合,因此测试Altimeter还需要测试EventSource.修复建议的更改如下:

--- a/src/main/scala/Altimeter.scala
+++ b/src/main/scala/Altimeter.scala
@@ -9,9 +9,10 @@ import  scala.concurrent.ExecutionContext.Implicits.global
 object Altimeter{
   case class RateChange(amount: Float) //sent to Altimeter
   case class AltitudeUpdate(altitude: Double)
+  def apply() = new Altimeter with ProductionEventSource
 }

-class Altimeter extends Actor with ActorLogging with EventSource{
+class Altimeter extends Actor with ActorLogging{ this: EventSource =>
   import Altimeter._

   val ceiling = 43000       //feet
diff --git a/src/main/scala/EventSource.scala b/src/main/scala/EventSource.scala
index 1fd5578..ded4f38 100755
--- a/src/main/scala/EventSource.scala
+++ …
Run Code Online (Sandbox Code Playgroud)

oop scala traits

1
推荐指数
1
解决办法
124
查看次数

为什么我不能指定特征的子类?

scala> class A
defined class A

scala> trait T extends A { val t = 1 }
defined trait T

//why can I do this?
scala> class B extends T
defined class B

scala> new B
res0: B = B@2e9c76

scala> res0.t
res1: Int = 1
Run Code Online (Sandbox Code Playgroud)

我认为,当你写作时trait T extends A,它会让你只能将特性T放在一个类的子类上A.那我为什么要戴上呢B?这只适用于你混入的时候吗?为什么在宣布课程时这是不可能的?

scala traits

0
推荐指数
1
解决办法
1459
查看次数