2011-11-09 3 views
12

私はScalaから始めて、これはちょっと変わったと感じました。私はスカラ座と似た何かをやろうとしているが、それは動作しませんなぜ他のクラスを拡張しないクラスは、特性から拡張する必要がありますか? (with does not work)

interface Foo{} 

public class Bar implements Foo{} 

trait Foo; 
class Bar with Foo; // This doesn't work! 

私は「拡張」キーワードを使用する必要がJavaで私はこのような何かを行うことができます:

class Bar extends Foo; // This works OK! 

これでいいですが、それは私が望むものではありません。だから

class Bar extends AnyRef with Foo; // This works too! 

私は何をしないのです:私はこれを行うことができます:私は指摘し

もう一つの奇妙なは(http://www.scala-lang.org/sites/default/files/images/classhierarchy.png scala-lang.orgからこの画像を参照)スカラ座で与えられたすべてのクラスがAnyRefから延びているということです?それを拡張せずに形質を使用する感覚はありませんか?

ありがとうございました!

答えて

21

最初のノート。私はそれが悪いことを意味するものではなく、言葉がそうでなければできなかったことだけである。 C#では、class A extends B implements C, Dclass A implements B, C, Dの代わりにclass A : B, C, Dと書いています。したがって、Scalaのextendsはコロンのようで、withはコンマのようなものだと考えることができます。

しかし、以前は、class Bar with Fooでした。 Scalaが2006年に2.0に戻ったときに変更されました。the change historyを参照してください。

理由は単にclass Bar with Fooがうまく読み込めないことを覚えていると思います。

スカラでは、A with BはタイプABの交差です。オブジェクトのタイプがAで、タイプがBの場合、オブジェクトのタイプはA with Bです。従ってが読み取られるかもしれないclass AB with Cのタイプを拡張します。 class A with Bでそのようなものはありません。

+0

良い説明、ありがとう! – santiagobasulto

3

Programming in Scala (2nd ed)はそれがextendsに関してノート第12章での特性について説明します。

あなたが特色で混合するためにextendsキーワードを使用することができます。その場合、 は、形質のスーパークラスを暗黙的に継承します。たとえば、リスト12.2のクラス FrogサブクラスAnyRef(スーパークラスPhilosophical)は、 Philosophicalに混在しています。

(ここで、Philosophicalが特徴です。)

だから、あなたの推理は正確に正しいです。

AnyRefの件名については、Scala class hierarchytop typesについてお読みください。 (AnyRefはトップタイプではありませんが、かなり近いです)

+0

私はその本を持っています!なぜ私はそれを逃したのですか?ありがとう@エミール – santiagobasulto

8

Javaから来ている場合は、最初は奇妙に聞こえるかもしれませんが(私にとっては同じでした)、実際はもっと普通の構文です私が明示的に私がimplementまたはextend他のクラス/インタフェースにしたいかどうかを言う必要があるJavaの。しかし私はそれが個人的な好みのより多くの問題だと思う。

extendsimplementsのどちらを指定してもかまいません。どちらも同じ種類の2つの関係を表します。です(委任と構成と対照的に、の関係を表します)。ここでは、例えば、あなたはそれについてのいくつかのより多くの情報を見つけることができます。

http://www.javacamp.org/moreclasses/oop/oop5.html

ただis aextendsimplementswithを交換しようとするとそれがより明確になります。

また、Scalaでは、is aという他のバリエーションもあります。例セルフタイプの場合:これにより

trait Bar { 
    self: Foo => 
    // ... 
} 

あなたはBar直接Foo /実装を拡張していないことを、言っているが、Barを拡張したい他のすべてのクラスは、またFooを拡張する必要があります。

自己タイプは興味深いものを許可することができます。たとえば、二つのクラス/互いに依存特性:違いはそれが分からないのであろうよりも、コンパイラに何も伝えていない実装/延びていることが

class Bar extends Foo { 
    def sayHello(name: String) = println("Hello, " + name) 

    greet() 
} 

trait Foo { 
    this: Bar => 

    def greet() = sayHello("User") 
} 

new Bar() // prints: Hello, User 
+0

も参照してくださいhttp://www.levinotik.com/2012/09/14/scala-abstract-classes-traits-and-self-types/ – ZiglioUK

+0

これは興味深い答えです、特に "自己タイプ"部。ありがとうございました! – asgs

関連する問題