Scalaの継承、abstract、mixinについて

Scalaの継承、abstract、mixinについて調べたのでブログに書いておきます。

継承について

まずは継承から説明していきます。

クラスを継承するにはextendsキーワードをつけます。
多重継承はできません。継承できるクラスは1つだけです。

finalで定義されたクラスは継承できません。

final class ClassName

abstractについて

次はabstractクラスを説明していきます。
abstractクラスはabstractキーワードを使って定義します。

abstract class AbstractClassName{
  /* 抽象メンバーを定義 
      普通のメンバも定義可能 */
}

abstractクラスはメンバーの具体的な定義をせず、継承した子クラスで具体的に定義するとき時に利用します。

・抽象メンバーにはabstractキーワードが不要(abstractクラスのメンバーはデフォルトが抽象メンバーになる)

メソッド以外にもフィールドを抽象化できる

scala> abstract class Greet {
     | //抽象フィールド
     | val value: String
     | //抽象メソッド
     | def morning(arg:String): String
     | }
defined class greet

scala> class Morning extends Greet {
     | //抽象フィールドの実装
     | val value = "Good morning"
     | //抽象メソッドの実装
     | def morning(arg: String) = "Good moning " + arg
     | }
defined class Morning

scala> val am = new Morning
am: morning = morning@36d64342

scala> am.Morning("scala")
res1: String = Good moning scala

scala> am.value
res2: String = Good morning

ちなみに抽象クラスを継承したクラスは、この抽象メソッドを必ずオーバーライドしなければいけません。(オーバーライドしないとコンパイルエラーに)

scala> class Morning extends Greet {
     | val value = "Good morning"
     | }
<console>:8: error: class Morning needs to be abstract, since method morning in class greet of type (arg: String)String is not defined
       class Morning extends Greet {
             ^

また抽象クラスに対してあまり使うイメージが湧かないという方は↓のページを見たらよりabstractクラスのユースケースがイメージできると思います。
http://www.itsenka.com/contents/development/java/abstract.html

トレイトとミックスインについて

トレイトはtraitキーワードによって定義します。通常のクラスのようにコンストラクタを持つことはできません。
抽象クラスのように抽象メンバーを定義することができます。
抽象メンバはトレイトがミックスインされる先のクラスで実装される必要があります。

ではトレイトの例をみていきます。

scala> trait ToSellPrice{
     | //抽象フィールド
     | val price:Int
     | def toSellPrice = price * 0.6
     | }
defined trait ToSellPrice

scala> class Iphone(color:String, capacity:Int ) extends ToSellPrice {
     | //抽象フィールドを定義しないとコンパイルエラーになる
     | val price = 900
     | }
defined class Iphone

scala> val myPhone = new Iphone( "silver", 32 )
myPhone: Iphone = Iphone@1996cd68

scala> myPhone.toSellPrice
res1: Double = 540.0

今回は継承しているクラスがないのでextendsでトレイトをミックスインしていますが、継承クラスがある場合はwith トレイト名というようにミックスインします。
複数トレイトをミックスインしたい場合はwith トレイト名 with トレイト名というように記述します。

ここで思ったのが、トレイトと抽象クラスってどっちを使えばいいの?ってことです。
やはり同じようなことを思った人がいるようで、それは↓の記事になります。
http://modegramming.blogspot.jp/2012/12/scala-tips_20.html

この違いはもっとコードを書くようになったら明確に分かると思うので、また別の機会にまとめてみます。


Scalaスケーラブルプログラミング第2版

Scalaスケーラブルプログラミング第2版

Guide to ScalaーScalaプログラミング入門

Guide to ScalaーScalaプログラミング入門