具体可以参考:《Effective Java》PECS 原则 (producser-extends, consumer-super)
G[+A]类似一个生产者,提供数据。(大部分情况下称G为容器类型)
G[-A] 是一个消费者,主要用来消费数据。(如上的 Equiv[-A] (其实就是个A => Boolean的函数,即Function1[-A, Boolean]))
同理函数的参数为何声明为逆变,返回值为协变就好理解了
同理
class G[+A]{def fun[B >: A](x: B){}}
就可理解为,我声明的是一个容器类型,但是它也有处理(消费数据)能力
参数逆变:正是因为需要符合里氏替换法则,方法中的参数类型声明时必须符合逆变(或不变),以让子类方法可以接收更大的范围的参数(处理能力增强);而不能声明为协变,子类方法可接收的范围是父类中参数类型的子集(处理能力减弱)。
返回值协变:如果结果类型是逆变的,那子类方法的处理能力是减弱的,不符合里氏替换。
目的:
协变和逆变的引入,当然是为了高阶类型F[A], F[B]之间, 也能像低阶类型A, B那样能够有型变的能力,如果List[String] 和 List[Any] 没什么关系,显然对不起“Scala是面向对象的”
时间: 2024-11-05 13:36:45