2016-07-08 5 views
2
私はScalaの型システムについてのマーティン・オーダーズキーとのインタビューを読んでいる

をタイプを識別してきました次は、ScalaはJavaのより表現力ある側面の構造的にScalaの

一つは、それはあなたが表現できていることですこれらの事。 Scalaでは、パラメータを取らずUnit(Javaではvoidと似ています)を返すcloseメソッドを持つものがあります。他の制約と組み合わせることもできます。あなたは言うことができます:これらの署名を持つこれらの特定のメソッドをさらに持つ特定のクラスから継承するもの。あるいは、あなたは言うことができます:このクラスから継承するものは、特定のタイプの内部クラスを持つものです。本質的に、タイプを構造的に特徴づけるには、そのタイプで何が必要かを言うことで、それらのタイプで作業することができます。

構造的にタイプを特定するには、Scalaでスニペットを書くことができますか?それを読んだ後、私は次のことを行うことができるはずな感覚を持っている:

type CanClose { def close: Unit } 
val closeableFile: CanClose = new File() 
val closeableStream: CanClose = new Stream() 
+0

を得る理由です

。 Googleの「Scala構造型」については、さらに詳しい情報があります。 – Jesper

+0

あなたの例については '' CanClose = {def close:Unit} ''( '='に注意してください) ''ファイル ''を意味する '' java.io.File'を ''閉じる'メソッド。 – Jesper

答えて

4

Scalaでは、型はその構造体によって識別でき、ダックタイピングと呼ばれることがあります。ここで

を例

scala> def close(x: { def close: Unit }): Unit = x.close 
warning: there was one feature warning; re-run with -feature for details 
close: (x: AnyRef{def close: Unit})Unit 

scala> class CanBeClosed { 
    | def close: Unit = println("I'm closed now") 
    | } 
defined class CanBeClosed 

scala> class CannotBeClosed { 
    | } 
defined class CannotBeClosed 

scala> close(new CanBeClosed) 
I'm closed now 

scala> close(new CannotBeClosed) 
<console>:13: error: type mismatch; 
found : CannotBeClosed 
required: AnyRef{def close: Unit} 
     close(new CannotBeClosed) 

だしかし、それは構造的なタイピングがランタイムリフレクションを使用して実装されていることに注意することが重要ですので、パフォーマンスへの影響を持つことができます。あなたは彼が構造タイプについて話している最初の定義に警告(あなたがimport scala.language.reflectiveCallsをインポートして警告を沈黙することができます)

+0

私は2.12が 'MethodHandles'と' invokedynamic'に切り替えると思うので、パフォーマンスのペナルティはすべて削除されるべきです。 –

1

マーティンはStructural Typesについて話しています。それはあなたが行うことができますすることができます意味:

scala> def anythingThatIsClosable(foo: { def close: Unit }): Unit = foo.close 
anythingThatIsClosable: (foo: AnyRef{def close: Unit})Unit 

scala> class ICanCloseResources { 
    | def close = println("yay closed") 
    | } 
defined class ICanCloseResources 

scala> anythingThatIsClosable(new ICanCloseResources()) 
yay closed 

我々は唯一の私たちはJavaが必要とのように、任意の共通のインタフェースを実際継承する必要はありませんでした、我々はタイプが動作するように期待するかの構造を定義しました。

例では、java.io.Fileclose()メソッドを実装していないため、機能しませんが、そのメソッドシグネチャに準拠している他のタイプは実現します。注意すべき重要な点の1つは、Scalaがreflectionに延期する必要があるため、潜在的にコストがかかることです。