Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/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重写方法_Scala_Design Patterns_Overriding - Fatal编程技术网

以子类作为参数类型的Scala重写方法

以子类作为参数类型的Scala重写方法,scala,design-patterns,overriding,Scala,Design Patterns,Overriding,我有一个trait a,它有一个方法def fun1(b:b):C 我希望A的子类实现B具有更详细的类型: 代码如下: trait B trait C trait A { def fun1( b:B ):C } class B1 extends B{ } class B2 extends B{ } class C1 extends C{ } class C2 extends C{ } 我希望A的子类可以声明如下 class X1 extends A{ override

我有一个
trait a
,它有一个方法
def fun1(b:b):C
我希望
A
的子类实现B具有更详细的类型:

代码如下:

trait B
trait C

trait A {
  def fun1( b:B ):C
}

class B1 extends B{
}

class B2 extends B{
}


class C1 extends C{
}

class C2 extends C{
}
我希望
A
的子类可以声明如下

class X1 extends A{
    override def fun1(b:B1):C1 = ...
}


class X2 extends A{
    override def fun1(b:B2):C2 = ...
}
但是,编译器会抱怨
X1不重写任何内容
。 我必须手动匹配详细的
B
的类型,如下所示

class X1 extends A{
    override def fun1(b:B):C = b match {case x:B1 => ... }
}


class X2 extends A{
    override def fun1(b:B2):C2 = b match {case x:B2 => ... }
}
此方法在编译期间无法检查正确的类型。如何实现第一个实现? 是否有任何设计模式来处理此问题


类似的问题是

您可以使用泛型类型参数执行此操作

trait A[T <: B] {
   def fun1( t:T ):C
}

class X1 extends A[B1]{
    override def fun1(b:B1):C1 = ...
}

trait A[T无法重写为更具体的类型。当为更具体的类型创建其他方法时,可以重载(删除重写)。将根据传递的实际参数调用最具体的方法

class X1 extends A{
  def fun1(b:B1):C1 = ...
}
在这种情况下,传递B1执行X1中的fun1,传递任何其他B执行a中的fun1


允许这种类型的重写实际上会阻止X1将B作为参数,只接受B1。这与Trait a声明和定义的方法直接冲突,无法重写它。如果允许重写,则X1.fun1(B:B)是不确定的。

无法优化继承方法的参数类型,因为方法/函数在它们上面是逆变的

考虑这个简化的例子:

trait A {
    def foo(b: Animal): Unit
}

trait Animal
class Cat extends Animal
class Dog extends Animal


class X1 extends A {
    def foo(b: Cat): Unit
}

class X2 extends A {
    def foo(b: Dog): Unit
} 

val list: List[A] = List(new X1, new X2)

这不会编译,但让我们先假设它会编译。如果我们需要迭代
列表
,并通过
foo
动物
传递给每个实例,会发生什么情况?
X1
应该能够处理任何
动物
,但它只接受
,如果使用
Dog
?你要求
X1
打破与
a
的契约,泛型是一种选择,但是fun1将只处理更具体的类型,而不是抽象类型(除非在trait中也定义了),你也可以使用抽象类型。trait a{type T最好使用
单位
以外的返回类型,因为在这种情况下有一种合理的答案:什么都不做。