Scala类型界限

Working with types in Scala can be challenging in many ways. The deeper you dig into the complexity of this subject, the more difficult is to find the right path. In this short post, I will be explaining some of the most fundamental of Scala type system — the type bounds. Enjoy!

在Scala中使用类型在许多方面都可能具有挑战性。 您越深入地研究该主题的复杂性,就越难找到正确的道路。 在这篇简短的文章中,我将解释Scala类型系统的一些最基本的概念-类型边界。 请享用!

什么是类型绑定? (What is type bound?)

A type bound is nothing more than a mechanism to add restrictions to the type parameters. When passing a type to let’s say a class, we can limit to what types we want to allow. This mechanism allows for greater control over our code and hopefully making it more robust.

类型绑定不过是向类型参数添加限制的机制。 当将类型传递给一个类时,我们可以限制我们要允许的类型。 这种机制可以更好地控制我们的代码,并希望使其更健壮。

There are 3 distinct type bounds available in Scala — upper bound, lower bound and upper and lower combined. The chapters below explain how to use each of them.

Scala中有3种不同的类型界限-上限,下限以及上限和下限。 以下各章说明了如何使用它们。

上限类型 (Upper type bound)

An upper type bound constraints a type A to be a subtype of B. The Scala notation looks like this:

上类型限制将类型A约束为B的子类型。 Scala表示法如下所示:

class SomeClass[A <: B]

The example above defines the type of A as a subtype of B. To understand it better, let's use some better example:

上面的示例将A的类型定义为B的子类型。 为了更好地理解它,让我们使用一些更好的示例:

trait Eatableclass Vegetable extends Eatable
class Meat extends Eatableclass Potato extends Vegetable
class Beef extends Meat
class Orange extends Eatableclass Vegan[A <: Vegetable]
class Carnivore[A <: Meat]
class Food[A <: Eatable]val vegan = new Vegan[Potato] // works fine
val mixed = new Carnivore[Potato] // error - type argument doesn't conform to type parameter bound
val all = new Food[Beef] // all good

As seen on a few examples above, the mechanism is pretty easy to use. The class Vegan, requires its type parameter to a subtype of Vegetable, which is exactly what Potato is. On the other hand, class Carnivore requires its parameter type to be a subtype of Meat, which Potato isn't hence the error. The Food class accepts any class that extends Eatable trait - a Beef is one of them.

从上面的几个示例可以看出,该机制非常易于使用。 Vegan类要求其类型参数为Vegetable的子类型,而Potato正是该类型。 另一方面,类Carnivore要求其参数类型为Meat的子类型,因此Potato并不是错误。 Food阶层接受任何扩展Eatable特征的阶层- Beef就是其中之一。

下界 (Lower type bound)

A lower type bounds works as one would expect — it limits the type A to be a supertype of B. The notation looks like this:

较低的类型界限可以像预期的那样工作-将类型A限制为B的超类型。 表示法如下所示:

class OtherClass[A >:  B]

The notation is similar to previous bound — only the less than sign is replaced with greater than sign. Let’s use the classes from previous examples to see the lower type bound in practice:

表示法与上一个界限类似-仅将小于号替换为大于号。 让我们使用前面示例中的类来了解实践中的下限类型:

trait Eatableclass Vegetable extends Eatable
class Meat extends Eatableclass Potato extends Vegetable
class Beef extends Meat
class Orange extends Eatableclass Stew[A >: Potato]
class BBQ[A >: Beef]
class Juice[A >: Orange]val stew = new Stew[Vegetable] // works fine
val BBQ = new BBQ[Meat] // fine as well
val juice = new Juice[Potato] // error

The lower type bound is similarly easy to use. We specify three more concrete classes: Stew, BBQ, and Juice. Stew requires its type parameter to a supertype of Potato, for BBQ the type parameter should be a supertype of Beef and for Juice - supertype of Orange. First to instantiations work fine, but the last one fails - the Potato is by no means a supertype of Orange, therefore an error is thrown.

下类型界限同样易于使用。 我们指定了另外三个具体的类: StewBBQJuiceStew要求它的类型参数为Potato ,对于BBQ ,类型参数应为Beef ,对于Juice - Orange父类。 首先实例化可以正常工作,但最后一个实例失败- Potato绝不是Orange的超类型,因此会引发错误。

上下限 (Lower and upper type bound)

Last example is actually a combination of previous two. Scala allows to define both lower and upper bounds in the same time. The notation for this looks like this:

最后一个示例实际上是前两个的组合。 Scala允许同时定义上下限。 表示法如下所示:

class LastClass[A <: B >: C]

In this example, the type A, has to be a subtype of B, while also being a supertype of C. As complicated as it may sound, it will be easier to understand using our 'food' examples:

在此示例中,类型A必须是B的子类型,同时还必须是C的超类型。 尽管听起来很复杂,但使用我们的“食物”示例将更容易理解:

trait Eatableclass Vegetable extends Eatable
class Meat extends Eatableclass Potato extends Vegetable
class Beef extends Meat
class Orange extends Eatableclass MarisPiper extends Potato
class Wagyu extends Beef
class Curacao extends Orangeclass RedMeat[A <: Meat >: Wagyu]
class RootVegetable[A <: Vegetable >: MarisPiper]val stew = new RedMeat[Beef] // all good
val BBQ = new RootVegetable[Potato] // works fine
val juice = new RootVegetable[MarisPiper] // error

This example should be fairly self-explanatory — we have two classes that use both upper and lower type bounds for their type parameters: RedMeat and RootVegetable. From the classes defined, the Beef works for the first one, and Potato for the second one. The Meat doesn't meet the upper type bound and Wagyu the lower type bound for RedMeat class type parameters.

这个例子应该是不言自明的—我们有两个类,它们的类型参数使用上限和下限类型: RedMeatRootVegetable 。 从定义的类中, Beef适用于第一个, Potato适用于第二个。 对于RedMeat类类型参数, Meat不满足上限类型, Wagyu不满足下限类型。

摘要 (Summary)

I hope you have found this post useful. If so, don’t hesitate to like or share this post. Additionally, you can follow me on my social media if you fancy so 🙂

我希望您发现这篇文章有用。 如果是这样,请随时喜欢或分享此帖子。 此外,如果您愿意,可以在我的社交媒体上关注我me

翻译自: https://medium.com/swlh/scala-type-bounds-a5ac37cc2467

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值