scala 协变和逆变_Scala方差:协变,不变和逆变

scala 协变和逆变

In this post, we are going to discuss about Scala Variance and it’s use cases.

在本文中,我们将讨论Scala Variance及其用例。

什么是方差? (What is Variance?)

Variance defines Inheritance relationships of Parameterized Types. Variance is all about Sub-Typing.

方差定义参数化类型的继承关系。 差异全都与子类型有关。

Please go through the following image to understand “What is Parameterized Type”.

请浏览下图以了解“什么是参数化类型”。

Here T is known as “Type Parameter” and List[T] is known as Generic.

在这里T被称为“类型参数”,而List [T]被称为泛型。

For List[T], if we use List[Int], List[AnyVal], etc. then these List[Int] and List[AnyVal] are known as “Parameterized Types”

对于List [T],如果我们使用List [Int],List [AnyVal]等,则这些List [Int]和List [AnyVal]被称为“参数化类型”

Variance defines Inheritance relationship between these Parameterized Types.

方差定义了这些参数化类型之间的继承关系。

Scala中的差异优势 (Advantage of Variance in Scala)

The main advantage of Scala Variance is:

Scala Variance的主要优点是:

  • Variance makes Scala collections more Type-Safe.

    差异使Scala集合更具类型安全性。
  • Variance gives more flexible development.

    差异使开发更加灵活。
  • Scala Variance gives us a technique to develop Reliable Applications.

    Scala Variance为我们提供了开发可靠应用程序的技术。

Scala中的方差类型 (Types of Variance in Scala)

Scala supports the following three kinds of Variance.

Scala支持以下三种方差。

  • Covariant

    协变
  • Invariant

    不变的
  • Contravariant

    逆变的

We will discuss these three variances in detail in coming sections.

我们将在接下来的部分中详细讨论这三个差异。

Scala中的协变 (Covariant in Scala)

If “S” is subtype of “T” then List[S] is is a subtype of List[T].

如果“ S”是“ T”的子类型,则List [S]是List [T]的子类型。

This kind of Inheritance Relationship between two Parameterized Types is known as “Covariant

两种参数化类型之间的这种继承关系称为“ 协变

Scala Covariance Syntax:-
To represent Covariance relationship between two Parameterized Types, Scala uses the following syntax:
Prefixing Type Parameter with “+” symbol defines Covariance in Scala.

Scala协方差语法:-
为了表示两个参数化类型之间的协方差关系,Scala使用以下语法:
带“ +”符号的前缀类型参数定义Scala中的协方差。

Here T is a Type Parameter and “+” symbol defines Scala Covariance.

这里T是类型参数,“ +”符号定义Scala协方差。

NOTE:- For simplicity reason, I’m using “List” here. However it may be any valid Scala Type like Set[+T], Ordered[+T] etc.

注意:-为简单起见,我在这里使用“列表”。 但是,它可以是任何有效的Scala类型,例如Set [+ T],Ordered [+ T]等。

Example:-
Write a Scala program to demo Scala Covariant SubTyping technique.

例:-
编写一个Scala程序来演示Scala协变量子类型技术。

class Animal[+T](val animial:T)

class Dog
class Puppy extends Dog

class AnimalCarer(val dog:Animal[Dog])

object ScalaCovarianceTest{
  def main(args: Array[String]) {
    val puppy = new Puppy
    val dog = new Dog

    val puppyAnimal:Animal[Puppy] = new Animal[Puppy](puppy)
    val dogAnimal:Animal[Dog] = new Animal[Dog](dog)

    val dogCarer = new AnimalCarer(dogAnimal)
    val puppyCarer = new AnimalCarer(puppyAnimal)

    println("Done.")
  }
}

NOTE:- As Animal class is defined by using Variance Annotation i.e. “+T”, we can pass either dogAnimal or its subtype puppyAnimal to create a AnimalCarer object.

注意:由于Animal类是通过使用方差注释(即“ + T”)定义的,因此我们可以传递dogAnimal或其子类型puppyAnimal来创建AnimalCarer对象。

If we remove Variance Annotation in Animal class definition, like as shown below:

如果我们在动物类定义中删除方差注释,如下所示:

class Animal[T](val animial:T)
// Remaining code is same as above.

It wont compile. We will get the following compilation error message:

它不会编译。 我们将收到以下编译错误消息:

Type mismatch, expected: Animal[Dog], found: Animal[Puppy]

To solve these kind of problems, we should use Scala Covariance.

为了解决这类问题,我们应该使用Scala协方差。

As per this example, we can say the following Scala Covariance:

根据此示例,我们可以说出以下Scala协方差:

“As Puppy is subtype of Dog, Animal[Puppy] is a subtype of Animal[Dog]. We can use Animal[Puppy] where we require Animal[Dog].” This is know as Scala Covariance.

“由于小狗是狗的亚型,所以动物[小狗]是动物[狗]的亚型。 我们可以在需要Animal [Dog]的地方使用Animal [Puppy]。” 这就是Scala协方差。

Scala中的变量 (Contravariant in Scala)

If “S” is subtype of “T” then List[T] is is a subtype of List[S].

如果“ S”是“ T”的子类型,则List [T]是List [S]的子类型。

This kind of Inheritance Relationship between two Parameterized Types is known as “Contravariant

两种参数化类型之间的这种继承关系称为“ Contravariant

Scala Contravariant Syntax:
To represent Contravariant relationship between two Parameterized Types, Scala uses the following syntax:
Prefixing Type Parameter with “-” symbol defines Contravariant in Scala.

Scala变量语法:
为了表示两个参数化类型之间的相反关系,Scala使用以下语法:
带“-”符号的前缀类型参数定义Scala中的Contravariant。

Example:-
Write a Scala program to demo Scala Contravariant SubTyping technique.

例:-
编写一个Scala程序以演示Scala逆向子类型化技术。

abstract class Type [-T]{
  def typeName : Unit
}

class SuperType extends Type[AnyVal]{
  override def typeName: Unit = {
    println("SuperType")
  }
}
class SubType extends Type[Int]{
  override def typeName: Unit = {
    println("SubType")
  }
}

class TypeCarer{
  def display(t: Type[Int]){
    t.typeName
  }
}

object ScalaContravarianceTest {

  def main(args: Array[String]) {
    val superType = new SuperType
    val subType = new SubType

    val typeCarer = new TypeCarer

    typeCarer.display(subType)
    typeCarer.display(superType)
  }

}

NOTE:-
As we define Contravariance in Type[-T], it works well. TypeCarer.display() is defined with Type[Int] i.e. SubType, but still it accepts Type[AnyVal] because Scala Contravariance subtyping.

注意:-
当我们在Type [-T]中定义Contravariance时,它运作良好。 TypeCarer.display()是用Type [Int](即SubType)定义的,但仍可以接受Type [AnyVal],因为Scala的Contravariance子类型化。

If we remove “-” definition in Type like “Type[T]”, then we will get compilation error.

如果我们在类型中删除“-”定义(如“ Type [T]”),则会出现编译错误。

Scala中的不变式 (Invariant in Scala)

If “S” is subtype of “T” then List[S] and List[T] don’t have Inheritance Relationship or Sub-Typing. That means both are unrelated.

如果“ S”是“ T”的子类型,则List [S]和List [T]没有继承关系或子类型。 这意味着两者无关。

This kind of Relationship between two Parameterized Types is known as “Invariant or Non-Variant

两种参数化类型之间的这种关系称为“ 不变或无变量

In Scala, by default Generic Types have Non-Variant relationship. If we define Parameterized Types without using “+’ or “-” symbols, then they are known as Invariants.

在Scala中,默认情况下,泛型类型具有Non-Variant关系。 如果我们在不使用“ +”或“-”符号的情况下定义参数化类型,则它们被称为不变式。

什么是Scala中的方差注释? (What is Variance Annotation in Scala?)

Variance Annotation means defining “+” or “-” before Type Parameters.

差异注释表示在类型参数之前定义“ +”或“-”。

Example:-
+T and – T are know as Variance Annotations in Scala.

例:-
+ T和– T在Scala中称为方差注释。

Scala方差摘要 (Scala Variance Summary)

In this section, we are going to summarize all 3 concepts we have discussed about Scala Variance Types in above sections.

在本节中,我们将总结在以上各节中讨论过的有关Scala方差类型的所有3个概念。

Scala Variance TypeSyntaxDescription
Covariant[+T]If S is subtype of T, then List[S] is also subtype of List[T]
Contravariant[-T]If S is subtype of T, then List[T] is also subtype of List[S]
Invariant[T]If S is subtype of T, then List[S] and List[T] are unrelated.
Scala方差类型 句法 描述
协变 [+ T] 如果S是T的子类型,则List [S]也是List [T]的子类型
逆变的 [-T] 如果S是T的子类型,则List [T]也是List [S]的子类型
不变的 [T] 如果S是T的子类型,则List [S]和List [T]不相关。

That’s it all about Scala Variance. We will discuss some more Scala concepts in my coming posts.

这就是Scala Variance的全部内容。 我们将在我的后续文章中讨论更多Scala概念。

Please drop me a comment if you like my post or have any issues/suggestions.

如果您喜欢我的帖子或有任何问题/建议,请给我评论。

翻译自: https://www.journaldev.com/9585/scala-variances-covariant-invariant-contravariant

scala 协变和逆变

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值