English 中文(简体)
使用抽象课程而不是海峡有什么好处?
原标题:What is the advantage of using abstract classes instead of traits?
  • 时间:2010-01-02 09:03:28
  •  标签:
  • scala
  • traits

使用抽象类别而不是海峡(除业绩外)有什么好处? 这似乎像抽象的班级一样,在多数情况下可以用海峡取代。

最佳回答

我可以考虑两个分歧。

  1. Abstract classes can have constructor parameters as well as type parameters. Traits can have only type parameters. There was some discussion that in future even traits can have constructor parameters
  2. Abstract classes are fully interoperable with Java. You can call them from Java code without any wrappers. Traits are fully interoperable only if they do not contain any implementation code
问题回答

在Schala的节目中,有一节称:“To trait, 或不适用于 trait?>, 涉及这一问题。 由于第1版可在网上查阅,我希望它能在这里引述全部内容。 (任何认真的Schala方案家应当购买该书):

Whenever you implement a reusable collection of behavior, you will have to decide whether you want to use a trait or an abstract class. There is no firm rule, but this section contains a few guidelines to consider.

If the behavior will not be reused, then make it a concrete class. It is not reusable behavior after all.

If it might be reused in multiple, unrelated classes, make it a trait. Only traits can be mixed into different parts of the class hierarchy.

If you want to inherit from it in Java code, use an abstract class. Since traits with code do not have a close Java analog, it tends to be awkward to inherit from a trait in a Java class. Inheriting from a Scala class, meanwhile, is exactly like inheriting from a Java class. As one exception, a Scala trait with only abstract members translates directly to a Java interface, so you should feel free to define such traits even if you expect Java code to inherit from it. See Chapter 29 for more information on working with Java and Scala together.

If you plan to distribute it in compiled form, and you expect outside groups to write classes inheriting from it, you might lean towards using an abstract class. The issue is that when a trait gains or loses a member, any classes that inherit from it must be recompiled, even if they have not changed. If outside clients will only call into the behavior, instead of inheriting from it, then using a trait is fine.

If efficiency is very important, lean towards using a class. Most Java runtimes make a virtual method invocation of a class member a faster operation than an interface method invocation. Traits get compiled to interfaces and therefore may pay a slight performance overhead. However, you should make this choice only if you know that the trait in question constitutes a performance bottleneck and have evidence that using a class instead actually solves the problem.

If you still do not know, after considering the above, then start by making it as a trait. You can always change it later, and in general using a trait keeps more options open.

正如“Mushtaq Ahmed”提到的那样,海峡不可能有任何参数传给某类主要建筑商。

另一个区别是处理<代码>super。

班级和海峡之间的另一区别是,在班级,super 电话是静态的,在海峡,电话是动态约束的。 如果您在某一班级书写<代码>super.toString,则你确切知道将采用哪种方法。 但是,如果你在海峡中写上同样的话,在你界定海峡时,援引超级呼吁的方法就没有界定。

详情见rel=“noreferer”第12章

<>>Edit 1 (2013年):

与海峡相比,抽象班的表现方式存在微妙的差别。 一条线性化规则是,它保留了这些阶层的继承等级,这倾向于在链条后面推导抽象的班级,而海峡可能好坏参半。 在某些情况下,这实际上比后一种情况更可取,因此可以为此使用如此抽象的课堂。 见constraining pararization (mixin Order) in Scala

<Edit 2 (2018):

截至2.12年,海峡双亲兼容性行为发生了变化。 在2.12之前,在海峡中增加或删除一个成员要求所有继承海峡的班次重新配对,即使这些班级没有改变。 这是因为证书在证书上编码了海峡。

截至Schala 2.12, traits , 因此,这一要求放宽了范围。 如果海峡有以下任何一种情况,其子类仍需要重新编造:

  • defining fields (val or var, but a constant is ok – final val without result type)
  • calling super
  • initializer statements in the body
  • extending a class
  • relying on linearization to find implementations in the right supertrait

但是,如果海峡没有,你现在可以更新,而不必打破双轨兼容性。

除了你不能直接提供多种抽象的课堂外,但你可以把多种海峡混为一谈,值得一提的是,海峡是站不住脚的,因为在海峡上的超级电话是动态的(指的是在现在之前混合的一类或海峡)。

https://stackoverflow.com/questions/2005681/difference-between-abstract-class-and-trait>。 摘要班和Trait之间的差别:

trait A{
    def a = 1
}

trait X extends A{
    override def a = {
        println("X")
        super.a
    }
}  


trait Y extends A{
    override def a = {
        println("Y")
        super.a
    }
}

scala> val xy = new AnyRef with X with Y
xy: java.lang.Object with X with Y = $anon$1@6e9b6a
scala> xy.a
Y
X
res0: Int = 1

scala> val yx = new AnyRef with Y with X
yx: java.lang.Object with Y with X = $anon$1@188c838
scala> yx.a
X
Y
res1: Int = 1

在延长抽象的班级时,这显示该子类类似。 我认为,在使用海峡时,情况并非绝对。

摘要班可以包含行为——他们可以与建筑群(海峡可以 t)连接起来,并代表一个工作实体。 追踪只是一个单一特征,一个功能的界面。

  1. A class can inherit from multiple traits but only one abstract class.
  2. Abstract classes can have constructor parameters as well as type parameters. Traits can have only type parameters. For example, you can’t say trait t(i: Int) { }; the i parameter is illegal.
  3. Abstract classes are fully interoperable with Java. You can call them from Java code without any wrappers. Traits are fully interoperable only if they do not contain any implementation code.




相关问题
How to flatten a List of different types in Scala?

I have 4 elements:List[List[Object]] (Objects are different in each element) that I want to zip so that I can have a List[List[obj1],List[obj2],List[obj3],List[obj4]] I tried to zip them and I ...

To use or not to use Scala for new Java projects? [closed]

I m impressed with Twitter and investigating to use Scala for a new large scale web project with Hibernate and Wicket. What do you think about Scala, and should I use it instead of Java? EDIT: And, ...

Why does Scala create a ~/tmp directory when I run a script?

When I execute a Scala script from the command line, a directory named "tmp" is created in my home directory. It is always empty, so I simply deleted it without any apparent problem. Of course, when I ...

Include jar file in Scala interpreter

Is it possible to include a jar file run running the Scala interpreter? My code is working when I compile from scalac: scalac script.scala -classpath *.jar But I would like to be able to include a ...

Scala and tail recursion

There are various answers on Stack Overflow which explain the conditions under which tail recursion is possible in Scala. I understand the limitations and how and where I can take advantage of tail ...

热门标签