Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.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抽象类型实现了从泛型trait扩展而来的trait_Scala_Functional Programming_Traits_Self Type - Fatal编程技术网

Scala抽象类型实现了从泛型trait扩展而来的trait

Scala抽象类型实现了从泛型trait扩展而来的trait,scala,functional-programming,traits,self-type,Scala,Functional Programming,Traits,Self Type,我是scala的新手,因此我的问题可能是因为对肠道类型和特征缺乏了解 我目前有一个传感器特性,它是通用的,定义了一个value和newValue方法 trait Sensor[T] { def value: T def newValue(): Unit = {} } class MemorySensor[T] extends Sensor[T] { var internalValue: T = null.asInstanceOf[T] def setValue(newVal:

我是scala的新手,因此我的问题可能是因为对肠道类型和特征缺乏了解

我目前有一个传感器特性,它是通用的,定义了一个value和newValue方法

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

}
传感器的一个具体实现是MemorySensor,它只使用一个变量来存储值,并有一个设置值的方法来设置值并触发newValue方法

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

}
还有一个AbstractSO(SO=subject+Observer)类,它使用抽象类型来实现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)

    }

}
现在我想为传感器实现一个具体的主体/观察者对,要求传感器主体应该是传感器的混合特征

因此,我想目标应该是像这样使用SensorSubject:

val x = new MemorySensor[Int] with SensorSubject[Int]
然而,无论我如何尝试实现SensorSO,我总是会遇到某种“非法继承”错误或“self-type不符合..”

据我所知,如果不创建一个从AbstractSO扩展而来的额外类,但使用泛型类型,就无法实现这一点。(但我不知道这如何帮助我实现目标)

如果有人能帮我,那就太好了

编辑:

由于SergGr希望看到我的SensorSubject(我不知道如何实现它,我将发布我的各种尝试之一)

但是请注意,这不会编译

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
  }
}
这是我的简历

class AbstractSensorSO extends AbstractSO {

  type S <: AbstractSensorSubject
  type O <: AbstractSensorObserver

  trait AbstractSensorSubject extends AbstractSubject  {
    this: S =>


  }

  trait AbstractSensorObserver extends AbstractObserver {

  }
}
但是,由于该上下文中不知道泛型类型“T”,因此它显然给出了一个错误(因为泛型“T”仅在泛型主题的上下文中可用) 如果我在定义类型S时尝试删除泛型参数,我还会收到一条错误消息,指出缺少泛型类型参数。 只是写作

type S = SensorSubject[Any]
也不能解决问题

EDIT2:

为了澄清我的目标是什么:

SensorSubject应该是一个混合特性,这样我可以使用普通传感器(不仅仅是MemorySensors),如果我愿意,我可以在传感器的创建中添加“with SensorSubject[Int]”,然后它就可以作为SensorSubject使用

这意味着我可以注册一个观察者,当我更改传感器的值时(现在作为SensorSubject运行)会通知观察者

下面是我想如何使用SensorSubject[T]特征的一个示例:

//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]]
输出将是

so.Main的新值$MemorySensorSubject@363ee3a2她42岁


这里最重要的可能是
MemorySensorSubject
是一个显式命名的类型,因此可以用作
S
中的
一个简单的经验法则:如果广泛使用类型级编程,那么就避免(实现)继承。特别是自我类型和混合。卢卡斯,你能展示一下你的
SensorSubject
实现吗?@SergGr我添加了我当前版本的SensorSubject,它有错误,但也许你可以帮我修复:)我非常感谢你花时间来帮助我。然而,这并不是我想要的确切结果。如果你想进一步帮助我,请看一下我的第二次编辑,在那里我试图澄清一点我希望主题如何work@LukasMakor,除了我使用显式命名的类
MemorySensorSubject
而不是
MemorySensor[Int]之外,我看不出我的代码与您试图实现的代码有什么不同使用SensorSubject[Int]
(我不知道如何避免您希望在Observer中保留类型安全性)。显然,您仍然可以在我的代码中创建
新的MemorySensor[Int]
,因为我的
MemorySensor
与您的完全相同。再次感谢您,因此我认为您的答案在现实世界的可用性方面非常好,但我之所以希望采用我描述的方式,是因为这是一个练习(我已经花了很多时间)在大学学习Scala初学者课程,教授要求我们按照我描述的方式实施。但是,如果没有其他人提出符合我要求的解决方案,我会接受你的回答(可能明天),因为我非常喜欢你的解决方案
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)
}