Scala中的动态继承

Scala中的动态继承,scala,inheritance,composition,Scala,Inheritance,Composition,我有一个名为grandparent的抽象祖父母类,一个名为ParentOne的父类,还有几个名为ChildOne,ChildTwo,ChildThree。。。等等 具体内容如下: abstract class Grandparent { val value: Int def print(): Unit = println(value) } class ParentOne extends Grandparent { override val value: Int = 1

我有一个名为
grandparent
的抽象祖父母类,一个名为
ParentOne
的父类,还有几个名为
ChildOne
ChildTwo
ChildThree
。。。等等

具体内容如下:

abstract class Grandparent {
    val value: Int
    def print(): Unit = println(value)
}

class ParentOne extends Grandparent {
    override val value: Int = 1
}

class ChildOne extends ParentOne
class ChildTwo extends ParentOne
class ChildThree extends ParentOne
我的目标是提供一种方法,将所有
子类中打印的
更改为例如
2
。我希望这个方法尽可能简单

结果将类似于如下所示创建一个类
ParentTwo
,并使所有
子类继承它,而不是
ParentOne

class ParentTwo extends Grandparent {
    override val value: Int = 2
}

但是我知道这是不可能的,因为我们不能动态地改变超类。我想使图书馆的结构变得更好,以完成上述任务。最简单的方法是什么?

如果你想要一个不变的解决方案,那么你必须引入一个成员。当前使用继承注入
值。但这不能在运行时更改

一种解决方案是让子类携带以下值:

class ChildOne(value: Int) extends GrandParent
然后客户端必须在每个对象创建时指定值。您可以引入生成器,因此客户端只需指定一次:

case class ChildBuilder(value: Int) {
  def buildChildOne = new ChildOne(value)
  def buildChildTwo = new ChildTwo(value)
}

> builder = ChildBuilder(2)
> val child1 = builder.buildChildOne
> val child2 = builder.buildChildTwo

我不知道这是否是一个可行的解决方案。不知怎的,我觉得你应该一起改变你的方法。但是我不知道你想要实现什么。

如果你想要一个不变的解决方案,那么你必须引入一个成员。当前使用继承注入
值。但这不能在运行时更改

一种解决方案是让子类携带以下值:

class ChildOne(value: Int) extends GrandParent
然后客户端必须在每个对象创建时指定值。您可以引入生成器,因此客户端只需指定一次:

case class ChildBuilder(value: Int) {
  def buildChildOne = new ChildOne(value)
  def buildChildTwo = new ChildTwo(value)
}

> builder = ChildBuilder(2)
> val child1 = builder.buildChildOne
> val child2 = builder.buildChildTwo
我不知道这是否是一个可行的解决方案。不知怎的,我觉得你应该一起改变你的方法。但是我不知道你想要实现什么。

你写的

我的目标是提供一种方法来改变

我将把它作为一个方法,它应该改变所有子类的值,对吗

如果是这样,您可以使用
父类
的伴生对象来存储一个变量,该变量可以随意更改:

abstract class Grandparent {
    def value: Int
    def print(): Unit = println(value)
}

object Parent {
    var mutableValue: Int = 1
}

class Parent extends Grandparent {
    override def value: Int = Parent.mutableValue
}

class ChildOne extends Parent
class ChildTwo extends Parent
class ChildThree extends Parent
使用示例:

pablo-pablo@ val c = new ChildOne() 
c: ChildOne = ammonite.$sess.cmd6$ChildOne@4ad10ef2
pablo-pablo@ c.value 
res12: Int = 12
pablo-pablo@ Parent.mutableValue = 30 

pablo-pablo@ c.value 
res14: Int = 30
你写的

我的目标是提供一种方法来改变

我将把它作为一个方法,它应该改变所有子类的值,对吗

如果是这样,您可以使用
父类
的伴生对象来存储一个变量,该变量可以随意更改:

abstract class Grandparent {
    def value: Int
    def print(): Unit = println(value)
}

object Parent {
    var mutableValue: Int = 1
}

class Parent extends Grandparent {
    override def value: Int = Parent.mutableValue
}

class ChildOne extends Parent
class ChildTwo extends Parent
class ChildThree extends Parent
使用示例:

pablo-pablo@ val c = new ChildOne() 
c: ChildOne = ammonite.$sess.cmd6$ChildOne@4ad10ef2
pablo-pablo@ c.value 
res12: Int = 12
pablo-pablo@ Parent.mutableValue = 30 

pablo-pablo@ c.value 
res14: Int = 30
使用隐式参数 需要
value
方法通过隐式参数获取值。 客户端可以创建
环境
,也可以提供可以导入的预制环境

请注意,实例将不拥有
。必须在每次方法调用时提供它

case class Environment(value: Int)

trait Parent {
  def value(implicit env: Environment): Int = env.value
}

class Child1 extends Parent
class Child2 extends Parent
//client code

implicit val env = Environment(2)

(new Child1).value == 2
(new Child2).value == 2
使用隐式参数 需要
value
方法通过隐式参数获取值。 客户端可以创建
环境
,也可以提供可以导入的预制环境

请注意,实例将不拥有
。必须在每次方法调用时提供它

case class Environment(value: Int)

trait Parent {
  def value(implicit env: Environment): Int = env.value
}

class Child1 extends Parent
class Child2 extends Parent
//client code

implicit val env = Environment(2)

(new Child1).value == 2
(new Child2).value == 2
混合溶液 混合溶液
谢谢你的反馈。我曾考虑过构建器类,但我有15个以上的类继承自
祖辈类
类,人们甚至可以添加更多继承自该类的类。因此,生成器类可能不合适。我正在寻找一个灵活的解决方案,但似乎很难想到。也许我得重新考虑一下应用程序的结构。谢谢你的反馈。我曾考虑过构建器类,但我有15个以上的类继承自
祖辈类
类,人们甚至可以添加更多继承自该类的类。因此,生成器类可能不合适。我正在寻找一个灵活的解决方案,但似乎很难想到。也许我必须重新考虑应用程序的结构。我想这是目前为止最好的解决方案。但是我不能否认它有一种使用全局变量的感觉。@SuhjinPark有点像,但不完全是这样,它更像是约束在类上下文中的静态变量。您可以将
mutableValue
设为私有,并将方法
changeValue
添加到
Parent
对象中,这是更改它的唯一方法。你可以将这个方法包私有化……我想这是目前为止最好的解决方案。但是我不能否认它有一种使用全局变量的感觉。@SuhjinPark有点像,但不完全是这样,它更像是约束在类上下文中的静态变量。您可以将
mutableValue
设为私有,并将方法
changeValue
添加到
Parent
对象中,这是更改它的唯一方法。您可以将该方法包设置为私有。。。