Scala 抽象类型实现了从通用特征扩展的特征
Scala abstract types implement trait that extends from generic trait
我是 scala 的新手,因此我的问题可能是由于缺乏对抽象类型和特征的理解。
我目前有一个 Sensor 特征,它是通用的并定义了一个值和 newValue 方法。
trait Sensor[T] {
def value: T
def newValue(): Unit = {}
}
Sensor 的一个具体实现是 MemorySensor,它只使用一个变量来存储值,并有一个设置值的方法来设置值并触发 newValue 方法。
class MemorySensor[T] extends Sensor[T] {
var internalValue: T = null.asInstanceOf[T]
def setValue(newVal: T): Unit = {
internalValue = newVal
newValue()
}
def value: T = internalValue
}
还有一个 AbstractSO (SO = subject + Observer) class 它使用抽象类型来实现 Subject/Observer 对。
class AbstractSO {
type O <: AbstractObserver
type S <: AbstractSubject
trait AbstractSubject {
this: S =>
def register(observer: O) = {
//we could use mutable collection here too
observers = observer :: observers
}
var observers: List[O] = List[O]()
def notifyObservers() = {
observers.foreach(o => o.notifyObserver(this))
}
}
trait AbstractObserver {
def notifyObserver(subject: S)
}
}
一个具体的例子 Subject/Observer 是 ActionSO
object ActionSO extends AbstractSO {
type S = ActionSubject
type O = ActionObserver
trait ActionSubject extends AbstractSubject {
def action() = {
notifyObservers()
}
}
trait ActionObserver extends AbstractObserver {
override def notifyObserver(actionSubject: ActionSubject) = {
println("action observer called")
}
}
}
现在我想实现一个具体的 Subject/Observer-Pair for Sensors,要求 SensorSubject 应该是传感器的混合特性。
所以我猜目标是像这样使用 SensorSubject:
val x = new MemorySensor[Int] with SensorSubject[Int]
然而,无论我尝试实现 SensorSO,我总是会遇到某种 "illegal inheritance" 错误或 "self-type does not conform to..".
据我所知,如果不创建一个从 AbstractSO 扩展但使用泛型类型的额外 class,就无法做到这一点。 (但我不知道这如何帮助我实现我的目标)
如果有人能帮帮我就太好了!
编辑:
由于 SergGr 想要查看我的 SensorSubject(这是我不知道如何实现的,我将 post 我的各种尝试之一)
但是请注意,这确实 无法编译
object SensorSO extends AbstractSensorSO {
//TODO: i shouldn´t use "Any" here - this won´t work
override type S = SensorSubject[Any]
trait SensorSubject[T] extends AbstractSensorSubject with Sensor[T] {
this: S => //this generates problems as well
}
}
这是我的 AbstractSensorSO
class AbstractSensorSO extends AbstractSO {
type S <: AbstractSensorSubject
type O <: AbstractSensorObserver
trait AbstractSensorSubject extends AbstractSubject {
this: S =>
}
trait AbstractSensorObserver extends AbstractObserver {
}
}
如您所见,AbstractSensorSO 基本上什么都不做,我只是添加了它,因为在解决方案的提示中提到,在创建具体的 SensorSO 之前,需要一个 AbstractSO 的子class对象。
我面临的一个问题是 Sensor 特征是通用的,因此 SensorSubject 要使用 Sensor 特征 AFAIK,我也必须使 SensorSubject 通用。
通常这不会成为问题,但是当我使用抽象类型时,我也必须使用泛型在 SensorSO 中定义 "S" 类型(例如
type S = SensorSubject[T]
但由于通用类型 "T" 在该上下文中未知,因此它显然会给出错误(因为通用 "T" 仅在通用特征 SensorSubject 的上下文中可用)
如果我在定义类型 S 时尝试删除通用参数,我还会收到一条错误消息,指出缺少通用类型参数。
并且只是写作
type S = SensorSubject[Any]
也没有解决问题
编辑2:
阐明我的目标是什么:
SensorSubject 应该是一个 Mixin Trait,这样我就可以使用普通的传感器(不仅是 MemorySensors),而且如果我愿意,我可以添加 "with SensorSubject[Int]" 到传感器的创建中,然后它作为一个 SensorSubject
这意味着我可以注册一个观察者,当我更改传感器(现在用作 SensorSubject)的值时,观察者会收到通知
这是我想如何使用 SensorSubject[T] Trait 的示例:
//creating a sensor WITH the SensorSubject Trait
val sensorWithSubject= new MemorySensor[Int] with SensorSubject[Int]
sensorWithSubject.registerObserver(..)
//creating a normal Sensor WITHOUT SensorSubject
val normalMemSensor = new MemorySensor[Int]
您没有提供任何预期用法示例,因此我的猜测可能是错误的。仍然是我的尝试:
trait Sensor[T] {
def value: T
def newValue(): Unit = {}
}
class MemorySensor[T] extends Sensor[T] {
var internalValue: T = null.asInstanceOf[T]
def setValue(newVal: T): Unit = {
internalValue = newVal
newValue()
}
def value: T = internalValue
}
//////////////////////////////////
trait AbstractSubject[S <: AbstractSubject[S, O], O <: AbstractObserver[S, O]] {
this: S =>
def register(observer: O) = {
//we could use mutable collection here too
observers = observer :: observers
}
private var observers: List[O] = List[O]()
def notifyObservers() = {
observers.foreach(o => o.notifyObserver(this))
}
}
trait AbstractObserver[S <: AbstractSubject[S, O], O <: AbstractObserver[S, O]] {
def notifyObserver(subject: S)
}
//////////////////////////////////
trait SensorSubject[T, S <: SensorSubject[T, S, O], O <: SensorObserver[T, S, O]] extends Sensor[T] with AbstractSubject[S, O] {
this: S =>
}
trait SensorObserver[T, S <: SensorSubject[T, S, O], O <: SensorObserver[T, S, O]] extends AbstractObserver[S, O]
//////////////////////////////////
class MemorySensorSubject[T] extends MemorySensor[T] with AbstractSubject[MemorySensorSubject[T], MemorySensorObserver[T]] {
override def setValue(newVal: T): Unit = {
super.setValue(newVal)
notifyObservers()
}
}
trait MemorySensorObserver[T] extends AbstractObserver[MemorySensorSubject[T], MemorySensorObserver[T]]
有了它你就可以做到
def test(): Unit = {
val sensor = new MemorySensorSubject[Int]
val observer = new MemorySensorObserver[Int] {
override def notifyObserver(subject: MemorySensorSubject[Int]): Unit = {
println(s"New value of $subject is ${subject.value}")
}
}
sensor.register(observer)
sensor.setValue(42)
}
输出将是
New value of so.Main$MemorySensorSubject@363ee3a2 is 42
可能这里最重要的是 MemorySensorSubject
是一个明确命名的类型,因此可以用作 F-bound generic constraint
中的 S
我是 scala 的新手,因此我的问题可能是由于缺乏对抽象类型和特征的理解。
我目前有一个 Sensor 特征,它是通用的并定义了一个值和 newValue 方法。
trait Sensor[T] {
def value: T
def newValue(): Unit = {}
}
Sensor 的一个具体实现是 MemorySensor,它只使用一个变量来存储值,并有一个设置值的方法来设置值并触发 newValue 方法。
class MemorySensor[T] extends Sensor[T] {
var internalValue: T = null.asInstanceOf[T]
def setValue(newVal: T): Unit = {
internalValue = newVal
newValue()
}
def value: T = internalValue
}
还有一个 AbstractSO (SO = subject + Observer) class 它使用抽象类型来实现 Subject/Observer 对。
class AbstractSO {
type O <: AbstractObserver
type S <: AbstractSubject
trait AbstractSubject {
this: S =>
def register(observer: O) = {
//we could use mutable collection here too
observers = observer :: observers
}
var observers: List[O] = List[O]()
def notifyObservers() = {
observers.foreach(o => o.notifyObserver(this))
}
}
trait AbstractObserver {
def notifyObserver(subject: S)
}
}
一个具体的例子 Subject/Observer 是 ActionSO
object ActionSO extends AbstractSO {
type S = ActionSubject
type O = ActionObserver
trait ActionSubject extends AbstractSubject {
def action() = {
notifyObservers()
}
}
trait ActionObserver extends AbstractObserver {
override def notifyObserver(actionSubject: ActionSubject) = {
println("action observer called")
}
}
}
现在我想实现一个具体的 Subject/Observer-Pair for Sensors,要求 SensorSubject 应该是传感器的混合特性。
所以我猜目标是像这样使用 SensorSubject:
val x = new MemorySensor[Int] with SensorSubject[Int]
然而,无论我尝试实现 SensorSO,我总是会遇到某种 "illegal inheritance" 错误或 "self-type does not conform to..".
据我所知,如果不创建一个从 AbstractSO 扩展但使用泛型类型的额外 class,就无法做到这一点。 (但我不知道这如何帮助我实现我的目标)
如果有人能帮帮我就太好了!
编辑:
由于 SergGr 想要查看我的 SensorSubject(这是我不知道如何实现的,我将 post 我的各种尝试之一)
但是请注意,这确实 无法编译
object SensorSO extends AbstractSensorSO {
//TODO: i shouldn´t use "Any" here - this won´t work
override type S = SensorSubject[Any]
trait SensorSubject[T] extends AbstractSensorSubject with Sensor[T] {
this: S => //this generates problems as well
}
}
这是我的 AbstractSensorSO
class AbstractSensorSO extends AbstractSO {
type S <: AbstractSensorSubject
type O <: AbstractSensorObserver
trait AbstractSensorSubject extends AbstractSubject {
this: S =>
}
trait AbstractSensorObserver extends AbstractObserver {
}
}
如您所见,AbstractSensorSO 基本上什么都不做,我只是添加了它,因为在解决方案的提示中提到,在创建具体的 SensorSO 之前,需要一个 AbstractSO 的子class对象。
我面临的一个问题是 Sensor 特征是通用的,因此 SensorSubject 要使用 Sensor 特征 AFAIK,我也必须使 SensorSubject 通用。 通常这不会成为问题,但是当我使用抽象类型时,我也必须使用泛型在 SensorSO 中定义 "S" 类型(例如
type S = SensorSubject[T]
但由于通用类型 "T" 在该上下文中未知,因此它显然会给出错误(因为通用 "T" 仅在通用特征 SensorSubject 的上下文中可用) 如果我在定义类型 S 时尝试删除通用参数,我还会收到一条错误消息,指出缺少通用类型参数。 并且只是写作
type S = SensorSubject[Any]
也没有解决问题
编辑2:
阐明我的目标是什么:
SensorSubject 应该是一个 Mixin Trait,这样我就可以使用普通的传感器(不仅是 MemorySensors),而且如果我愿意,我可以添加 "with SensorSubject[Int]" 到传感器的创建中,然后它作为一个 SensorSubject
这意味着我可以注册一个观察者,当我更改传感器(现在用作 SensorSubject)的值时,观察者会收到通知
这是我想如何使用 SensorSubject[T] Trait 的示例:
//creating a sensor WITH the SensorSubject Trait
val sensorWithSubject= new MemorySensor[Int] with SensorSubject[Int]
sensorWithSubject.registerObserver(..)
//creating a normal Sensor WITHOUT SensorSubject
val normalMemSensor = new MemorySensor[Int]
您没有提供任何预期用法示例,因此我的猜测可能是错误的。仍然是我的尝试:
trait Sensor[T] {
def value: T
def newValue(): Unit = {}
}
class MemorySensor[T] extends Sensor[T] {
var internalValue: T = null.asInstanceOf[T]
def setValue(newVal: T): Unit = {
internalValue = newVal
newValue()
}
def value: T = internalValue
}
//////////////////////////////////
trait AbstractSubject[S <: AbstractSubject[S, O], O <: AbstractObserver[S, O]] {
this: S =>
def register(observer: O) = {
//we could use mutable collection here too
observers = observer :: observers
}
private var observers: List[O] = List[O]()
def notifyObservers() = {
observers.foreach(o => o.notifyObserver(this))
}
}
trait AbstractObserver[S <: AbstractSubject[S, O], O <: AbstractObserver[S, O]] {
def notifyObserver(subject: S)
}
//////////////////////////////////
trait SensorSubject[T, S <: SensorSubject[T, S, O], O <: SensorObserver[T, S, O]] extends Sensor[T] with AbstractSubject[S, O] {
this: S =>
}
trait SensorObserver[T, S <: SensorSubject[T, S, O], O <: SensorObserver[T, S, O]] extends AbstractObserver[S, O]
//////////////////////////////////
class MemorySensorSubject[T] extends MemorySensor[T] with AbstractSubject[MemorySensorSubject[T], MemorySensorObserver[T]] {
override def setValue(newVal: T): Unit = {
super.setValue(newVal)
notifyObservers()
}
}
trait MemorySensorObserver[T] extends AbstractObserver[MemorySensorSubject[T], MemorySensorObserver[T]]
有了它你就可以做到
def test(): Unit = {
val sensor = new MemorySensorSubject[Int]
val observer = new MemorySensorObserver[Int] {
override def notifyObserver(subject: MemorySensorSubject[Int]): Unit = {
println(s"New value of $subject is ${subject.value}")
}
}
sensor.register(observer)
sensor.setValue(42)
}
输出将是
New value of so.Main$MemorySensorSubject@363ee3a2 is 42
可能这里最重要的是 MemorySensorSubject
是一个明确命名的类型,因此可以用作 F-bound generic constraint
S