Trait混合中的限制

10

我想要有一些只能混合指定特性的类:

class Peter extends Human with Lawful with Evil
class Mag extends Elf with Chaotic with Neutral

在Scala中有一种方法可以做到这一点吗?

更新:

trait Law
trait Lawful extends Law
trait LNeutral extends Law
trait Chaotic extends Law

trait Moral
trait Good extends Moral
trait Neutral extends Moral
trait Evil extends Moral

class Hero .........
class Homer extends Hero with Chaotic with Good

我想以一种方式定义一个Hero类,以便约束客户端程序员在扩展Hero类时必须混合特定的特性(Lawful/LNeutral/ChaoticGood/Neutral/Evil)。并且我想找到其他限制/约束客户端代码的可能性。


我写了一个答案,但是在重新阅读你的问题后,我认为你只想要邪恶/中立/善良与守法/中立/混乱的有效组合。更详细地解释一下你所寻找的内容可能会有帮助。 - David Holbrook
3个回答

28
坚强点,试试这个:
scala> trait Law[T]
defined trait Law

scala> trait Lawful extends Law[Lawful]
defined trait Lawful

scala> trait Chaotic extends Law[Chaotic]
defined trait Chaotic

scala> class Peter extends Lawful with Chaotic
<console>:8: error: illegal inheritance;
 class Peter inherits different type instances of trait Law:
Law[Chaotic] and Law[Lawful]
       class Peter extends Lawful with Chaotic
             ^

如果你想要将Law类型作为必须扩展的需求,那么你需要在某个基类或特质中使用自身类型:

scala> class Human {
     |   self: Law[_] =>
     | }
defined class Human

scala> class Peter extends Human
<console>:7: error: illegal inheritance;
 self-type Peter does not conform to Human's selftype Human with Law[_]
       class Peter extends Human
                           ^

并且还有一些进一步的调整,以确保更高的类型安全性。最终结果可能如下所示:

sealed trait Law[T <: Law[T]]
trait Lawful extends Law[Lawful]
trait LNeutral extends Law[LNeutral]
trait Chaotic extends Law[Chaotic]

sealed trait Moral[T <: Moral[T]]
trait Good extends Moral[Good]
trait Neutral extends Moral[Neutral]
trait Evil extends Moral[Evil]

class Human {
  self: Law[_] with Moral[_] =>
}

哦,我可以再说一件事:当你从人类继承时,应该写成“object James_Raynor extends Human with Chaotic with Good”,而不是“object James_Raynor extends Human with Law[Chaotic] with Moral[Good]”。 - Jeriho
@Jeriho 嗯,除了定义 LawMoral 的文件外,您无法在其他文件中执行此操作,因为这些特性是 sealed 的,意味着您不能在该文件之外的子类化它们。 - Daniel C. Sobral
这里的“抽象特征”是否与“特征”有任何不同的含义? - Seth Tisue
@Seth 这意味着原来的示例使用了 class,后来我将其更改为 trait。既然你提出了这个问题,我甚至检查了 abstract trait 是否在语法上有效(是的)。无论如何,我都会修复代码。 - Daniel C. Sobral
美妙的 <3 我想知道是否有使用类型参数的好方法。 - Raphael

9
也许您正在寻找限制自我类型声明的方法。例如:
class Human
trait Lawful
trait Lawless

class NiceGuy
extends Human
{
  this: Lawful =>
}

class BadGuy
extends Human
{
  this: Lawless =>
}


scala> class SuperHero extends NiceGuy
<console>:7: error: illegal inheritance;
 self-type SuperHero does not conform to NiceGuy's selftype NiceGuy with Lawful
       class SuperHero extends NiceGuy
                               ^

scala> class SuperHero extends NiceGuy with Lawful
defined class SuperHero

scala> class SuperVillain extends BadGuy
<console>:7: error: illegal inheritance;
 self-type SuperVillain does not conform to BadGuy's selftype BadGuy with Lawless
       class SuperVillain extends BadGuy
                                  ^

scala> class SuperVillain extends BadGuy with Lawless
defined class SuperVillain

那么,如果例如BadGuy需要Lawless,与仅从Lawless继承BadGuy相比,有何优势?假设Lawless有任何子类? - Erik Kaplun
自类型注释不会对其应用的特质或类的公共类型身份产生影响。我通常将其描述为类似于C++私有继承,尽管实际上它们是非常不同的。使用C++私有继承,您实际上是继承了某些东西。而使用受限Scala的受限自类型,您只需创建混合指定类型的义务,以最终得到可实例化的类。 - Randall Schulz

0

您可以在 Human 和/或 Elf 的构造函数中检查其是否是允许的特征实例:

class Human {
  if (this.instanceOf[Lawful] && this.instanceOf[Chaotic])
    throw new AlignmentException("A Human can only be either Lawful or Chaotic")
}

好的,原帖没有具体说明 :-) - RoToRa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接