2014年8月25日月曜日

Programming in Scala, First Edition: Chapter 29

29. Combining Scala and Java
  scalaはJavaのprogramやframeworkと一緒に使われることが多い。
  scalaはJavaの互換性が高いので、普通に使っている分には問題ない。
  それでも時々はJavaとの組み合わせで問題になる場合もある。
  ScalaからJavaへの変換
    特にJavaからScalaを呼び出すときに重要。
  JavaのannotationsをScalaから使う。
    Scalaを既存のJavaのframeworkで使う場合に重要。

29.1 Using Scala from Java
  General rules
    Scalaは標準のJavaのバイトコードに変換される。
    可能な限りScalaの機能はJavaの機能に直接対応付けられている。
      class, method, string, exception等。
      overloaded methodの実行時解決もJavaと同様に出来ない。
        ScalaではやりたかったがJavaと合わせるために諦めた。
    Scala独自の機能もある。
      trait, generic type等
      Javaが持っている複数の機能を組み合わせて実装されている。
      どの様にJavaに変換するかは日々進化している。
        javapの様なツールを使って".class"ファイルを調べれば変換の詳細が分かる。
  Value types
    Int等は可能な限りint等に変換しようとする。
      性能面で有利だから。
    int等が使えるかわからない場合はjava.lang.Integer等のwrapper classeに変換。
      List[Any]に格納しようとする場合等。
  Singleton objects
    Javaのstaticとinstance methodの組み合わせに変換される。
    名前の末尾に$が付加されたJavaのclassが作られる。
    MODULE$というstaticのfieldが付加される。
      起動時にそのclassのinstanceが一つ生成されて格納される。
    同じ名前のclassを持たないstandaloneの場合は異なる。
      $が付かない同じ名前のclassに変換される。
      methodは直接static methodに変換される。
  Traits as interfaces
    ScalaのTraitsは同名のJavaのInterfaceを生成する。
    Javaのtypeとして使える。そのtypeの変数を通してScalaのobjectのmethodを呼べる。
    TraitsのJavaでの実装するのは実用的ではない。
    全てがabstract methodのTraitはJavaのInterfaceに直接変換される。
      JavaのInterfaceをScalaで定義する事が出来る。

29.2 Annotations
  Additional effects from standard annotations
    コンパイラがJava特有の付加的な情報を吐き出す場合がある。
      先にScalaの一般的なルールをチェックして、その後にJava特有の処理を行う。
    Deprecation
      JavaコードがScalaのmethodにアクセスした際にJavaコンパイラが警告を出す。
        ScalaのコンパイラがJavaのdeprecation annotationを付加するので。
    Volatile
      Javaのvolatile modifierと全く同じ効果を持つ。
        ScalaのコンパイラがJavaのvolatile modifierを付加するので。
    Serialization
      @serializable class -> Javaの Serializable interfaceが付加される。
      @SerialVersionUID(1234L) -> private final static long SerialVersionUID = 1234L;
      @transient -> Java transient modifier.
  Exceptions thrown
    Scalaでは例外が補足されるかどうかをチェックしない。
      Javaではどの例を投げるか宣言して、それが補足されているチェックしている。
      でもこれが失敗だったのでScalaでは止めている。
        警告を止めるためにだけに意味の無い例が処理が掛かれることが多かった。
        これは単にコードを読みにくくしているだけ。
    Scalaのmethodは例外を投げない宣言でJavaに変換される。
    JavaからScalaのコード使う際に投げる例外の宣言が必要になる事がある。
      @throws(classOf[IOException]) def read() = in.read()
      上記でIOExceptionを投げる宣言が出来る。
  Java annotations
    Java frameworkの全てのannotationは直接Scalaでも使う事が出来る。
      Javaで書いているのと同じように書けばよい。
  Writing your own annotations
    Javaのreflectionから使えるannotationを作る。
      Scala内でJavaの記法で書いて、javacでコンパイルすれば作れる。
      Scala内に各意味が無いのでScalaのコンパイラではサポートしていない。
        Scalaが何時か自身のreflectionをサポートする時にはサポートするかも。

29.3 Existential types
  Existential typesはJavaのtypeにScalaからアクセスする時に使われる。
    言語仕様の一部としてJavaとは関係なくサポートされてはいるが。
  宣言の仕方
    type forSome { declarations }
  JavaのIterator<?>のScalaでの宣言
    Iterator[T] forSome { type T }
      Iterator[_] と書いても良い。
  JavaのIterator<? extends Component>のScalaでの宣言
    Iterator[T] forSome { type T <: Component }
      Iterator[_ <: Component] と書いても良い。
  Existential typesを使えばTがJava内にあってScala内では不明の場合でも、Tが分からないくても使えるmethod等は呼べる。
  Iterator<?>の?の型を参照する必要がある場合
    型パラメータTありのmethodの引数としてJavaからコールしてもらう。
      型を参照できるようになる。
    戻り値として返す時はabstract typeをmemberとして持つabstract classのtypeをTで確定したobjectを返すようにする。

29.4 Conclusion
  Javaと連携させる時はScalaのJava上の実装も意識する必要がある。

0 件のコメント:

コメントを投稿