自我类型和特质子类有什么区别? [英] What is the difference between self-types and trait subclasses?

查看:22
本文介绍了自我类型和特质子类有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

特征的自类型A:

trait B
trait A { this: B => }

"A不能混合到一个不扩展B"的具体类中.

says that "A cannot be mixed into a concrete class that does not also extend B".

另一方面,以下内容:

trait B
trait A extends B

A 中混合的任何(具体或抽象)类也将混合在 B 中".

says that "any (concrete or abstract) class mixing in A will also be mixing in B".

这两个陈述不是一个意思吗?self 类型似乎只是为了创造一个简单的编译时错误的可能性.

Don't these two statements mean the same thing? The self-type seems to serve only to create the possibility of a simple compile-time error.

我错过了什么?

推荐答案

主要用于依赖注入,例如在蛋糕模式中.有一篇很棒的文章,涵盖了 Scala 中许多不同形式的依赖注入,包括蛋糕图案.如果您在 Google 上搜索Cake Pattern and Scala",您将获得许多链接,包括演示文稿和视频.目前,这里是另一个问题的链接.

It is predominately used for Dependency Injection, such as in the Cake Pattern. There exists a great article covering many different forms of dependency injection in Scala, including the Cake Pattern. If you Google "Cake Pattern and Scala", you'll get many links, including presentations and videos. For now, here is a link to another question.

现在,至于 self 类型和扩展 trait 之间的区别是什么,这很简单.如果你说B extends A,那么B 一个A.当您使用自类型时,B 需要一个 A.使用 self 类型创建了两个特定要求:

Now, as to what is the difference between a self type and extending a trait, that is simple. If you say B extends A, then B is an A. When you use self-types, B requires an A. There are two specific requirements that are created with self-types:

  1. 如果 B 被扩展,那么你需要混合一个 A.
  2. 当一个具体的类最终扩展/混合这些特征时,某些类/特征必须实现A.
  1. If B is extended, then you're required to mix-in an A.
  2. When a concrete class finally extends/mixes-in these traits, some class/trait must implement A.

考虑以下示例:

scala> trait User { def name: String }
defined trait User

scala> trait Tweeter {
     |   user: User =>
     |   def tweet(msg: String) = println(s"$name: $msg")
     | }
defined trait Tweeter

scala> trait Wrong extends Tweeter {
     |   def noCanDo = name
     | }
<console>:9: error: illegal inheritance;
 self-type Wrong does not conform to Tweeter's selftype Tweeter with User
       trait Wrong extends Tweeter {
                           ^
<console>:10: error: not found: value name
         def noCanDo = name
                       ^

如果TweeterUser 的子类,则不会有错误.在上面的代码中,每当使用 Tweeter 时,我们要求一个 User,但是没有提供 User错误,所以我们得到了一个错误.现在,由于上面的代码仍在范围内,请考虑:

If Tweeter was a subclass of User, there would be no error. In the code above, we required a User whenever Tweeter is used, however a User wasn't provided to Wrong, so we got an error. Now, with the code above still in scope, consider:

scala> trait DummyUser extends User {
     |   override def name: String = "foo"
     | }
defined trait DummyUser

scala> trait Right extends Tweeter with User {
     |   val canDo = name
     | }
defined trait Right 

scala> trait RightAgain extends Tweeter with DummyUser {
     |   val canDo = name
     | }
defined trait RightAgain

使用Right,满足混入User 的要求.然而,上面提到的第二个要求并没有得到满足:实现 User 的负担仍然存在于扩展 Right 的类/特征.

With Right, the requirement to mix-in a User is satisfied. However, the second requirement mentioned above is not satisfied: the burden of implementing User still remains for classes/traits which extend Right.

使用 RightAgain 可以满足这两个要求.提供了一个 User 和一个 User 的实现.

With RightAgain both requirements are satisfied. A User and an implementation of User are provided.

有关更多实际用例,请参阅本答案开头的链接!但是,希望现在你明白了.

For more practical use cases, please see the links at the start of this answer! But, hopefully now you get it.

这篇关于自我类型和特质子类有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆