LoginSignup
32
25

More than 5 years have passed since last update.

Scalaのクラスについて

Last updated at Posted at 2014-03-09

クラスの宣言、コンストラクタ

宣言とインスタンス化

シンプルなクラス宣言

SimpleClass.scala
/** class and instance sample */
class SimpleClass {
}

new でインスタンス化できる。

scala> val hoge = new SimpleClass
hoge: SimpleClass = SimpleClass@51ea07a3

基本コンストラクタ

デフォルトコンストラクタでの処理はクラス内に直接記載すればよい。

SimpleClass.scala
/** class and instance sample */
class SimpleClass {
  // インスタンス化のタイミングで実行される。
  println("create SimpleClass") 
}

scala> val hoge = new SimpleClass
create SimpleClass
hoge: SimpleClass = SimpleClass@5db2381b

コンストラクタが引数をもつ場合は、宣言時にクラス名の後ろに引数を定義する。

SimpleClass.scala
/** class and instance sample */
class SimpleClass(id:String) {
  // インスタンス化のタイミングで実行される。
  println("create SimpleClass id:" + id)
}

scala> val hoge = new SimpleClass("test")
create SimpleClass id:test
hoge: SimpleClass = SimpleClass@40ab627a

基本コンストラクタが引数有りなので、引数なしではインスタンス化できない。

scala> val hoge = new SimpleClass
:7: error: not enough arguments for constructor SimpleClass: (id: String)SimpleClass.
Unspecified value parameter id.
val hoge = new SimpleClass

補助コンストラクタ

基本コンストラクタ以外のコンストラクタを定義する場合は、 sub this(...) で定義する。
補助コンストラクタは、必ず始めに基本コンストラクタを呼ばないといけない。

SimpleClass.scala
/** class and instance sample */
class SimpleClass(id:String) {
  // インスタンス化のタイミングで実行される。
  println("create SimpleClass id:" + id)

  // 補助コンストラクタ
  def this() {
    // 先頭で基本コンストラクタを呼び出す必要がある。
    this("dummy");
    println("create by sub contracter")
  }
}

scala> val piyo = new SimpleClass
create SimpleClass id:dummy
create by sub contracter
piyo: SimpleClass = SimpleClass@5babd8cb

メソッドの宣言

メソッド宣言の基本

def メソッド名(引数):戻り値 でメソッドを宣言する。ドット指定で呼び出せる。

SimpleClass2.scala
/** method sample */
class SimpleClass2 {

  def sayHello(name:String):Unit = {
    println("hello, " + name + "!!");
  }
}

scala> val hello = new SimpleClass2
hello: SimpleClass2 = SimpleClass2@75bc45de

scala> hello.sayHello("taro")
hello, taro!!

オーバーロード

引数の数、型を変えることで同名のメソッドを定義できる。

SimpleClass2.scala
/** method sample */
class SimpleClass2 {

  def sayHello(name:String):Unit = {
    println("hello, " + name + "!!");
  }

  // 引数が異なればオーバーロード可能
  def sayHello(times:Int):Unit = {
    println("hello," * times);
  }
  def sayHello(name:String, times:Int):Unit = {
    println(( "hello," * times ) + " " + name + "!!");
  }

  // 戻り値が異なるメソッドは定義できない。
  /* 以下はコンパイルエラーになる。
  def sayHello(times:Int):String = {
    "hello" * times;
  }
  */
}

scala> val hello = new SimpleClass2
hello: SimpleClass2 = SimpleClass2@2448b7f

scala> hello.sayHello("jiro")
hello, jiro!!

scala> hello.sayHello(3)
hello,hello,hello,

名前付き引数

引数名を指定して呼び出すことで、定義順を無視して引数を指定することができる。

scala> hello.sayHello("hoge",3)
hello,hello,hello, hoge!!

scala> hello.sayHello(times=3, name="hoge")
hello,hello,hello, hoge!!

引数のデフォルト値
SimpleClass2.scala
/** method sample */
class SimpleClass2 {

  def sayHello(name:String):Unit = {
    println("hello, " + name + "!!");
  }

  // 引数が異なればオーバーロード可能
  def sayHello(times:Int):Unit = {
    println("hello," * times);
  }
  def sayHello(name:String, times:Int):Unit = {
    println(( "hello," * times ) + " " + name + "!!");
  }

  // 戻り値が異なるメソッドは定義できない。
  /* 以下はコンパイルエラーになる。
  def sayHello(times:Int):String = {
    "hello" * times;
  }
  */

  // 引数にデフォルト値を定義
  def sayBye(name:String, times:Int = 3):Unit =  {
    println( ("Bye,"*times) + " " + name + "!!" );
  }
}

引数にデフォルト値を定義することで、メソッド呼び出し時に引数を省略することができる。

scala> hello.sayBye("tanaka", 2)
Bye,Bye, tanaka!!

scala> hello.sayBye("tanaka")
Bye,Bye,Bye, tanaka!!

暗黙の引数

引数の型に implicit を書くと、暗黙の引数となる。
引数を省略した際に、呼び出し先のスコープにて implicit 付きで定義された変数が暗黙的に設定される。

SimpleClass2.scala
/** method sample */
class SimpleClass2 {

  def sayHello(name:String):Unit = {
    println("hello, " + name + "!!");
  }

  // 引数が異なればオーバーロード可能
  def sayHello(times:Int):Unit = {
    println("hello," * times);
  }
  def sayHello(name:String, times:Int):Unit = {
    println(( "hello," * times ) + " " + name + "!!");
  }

  // 戻り値が異なるメソッドは定義できない。
  /* 以下はコンパイルエラーになる。
  def sayHello(times:Int):String = {
    "hello" * times;
  }
  */

  // 引数にデフォルト値を定義
  def sayBye(name:String, times:Int = 3):Unit =  {
    println( ("Bye,"*times) + " " + name + "!!" );
  }

  // 暗黙の引数を定義
  def greet(implicit name:String):Unit = {
    println( "Hi! " + name );
  }
}

scala> val hello = new SimpleClass2
hello: SimpleClass2 = SimpleClass2@4e1f52a

scala> implicit val name = "tanaka"
name: String = tanaka

scala> hello.greet
Hi! tanaka

scala> hello.greet("sato")
Hi! sato

変数が定義されていないとコンパイルエラーになる。

scala> val hello = new SimpleClass2
hello: SimpleClass2 = SimpleClass2@4e1f52a

scala> hello.greet
:9: error: could not find implicit value for parameter name: String
hello.greet
^

フィールドとアクセサ

フィールドの宣言

フィールドはクラス内に直接定義できる。

SimpleClass3.scala
/** field sample */
class SimpleClass3 {
  // 変更可能なフィールド
  var var_id:Int = 1;
  // 不変なフィールド
  val val_id:Int = 2;
  // 外部から参照できないフィールド
  private val private_id = 999;
}

外部からはフィールド名指定での参照・設定が可能。

scala> val hoge = new SimpleClass3
hoge: SimpleClass3 = SimpleClass3@10f8ed

scala> hoge.var_id
res0: Int = 1

scala> hoge.var_id = 3
hoge.var_id: Int = 3

scala> hoge.var_id
res1: Int = 3

不変なフィールドは参照のみ可能。

scala> hoge.val_id = 3
:8: error: reassignment to val
hoge.val_id = 3
^

privateなフィールドは参照も不可。

scala> hoge.private_id
:9: error: value private_id in class SimpleClass3 cannot be accessed in SimpleClass3
hoge.private_id
^

アクセサ

フィールドへのアクセスは、暗黙的に生成されるアクセサを経由して行われている。
getterは変数名、setterは変数名_=(xxx)だが、変数名=xxxという形式でも呼び出せる。(こちらのほうが自然)

SimpleClass3.scala
/** field sample */
class SimpleClass3 {
  // 変更可能なフィールド
  var id:Int = _; // _ は型のデフォルト値
}

scala> val hoge = new SimpleClass3
hoge: SimpleClass3 = SimpleClass3@6143c610

scala> hoge.id = 3
hoge.id: Int = 3

scala> hoge.id_=(999)

scala> hoge.id
res5: Int = 999

明示的にアクセサを定義する場合は、上記ルールに則ってメソッドを定義し、フィールドはprivateにしてアクセスを制約すればよい。
呼び出し元に変化がないところがポイント

SimpleClass3.scala
/** field sample */
class SimpleClass3 {
  // アクセサを独自実装するため、privateとする。
  private var _id:Int = _; // _ は型のデフォルト値

  // getter
  def id:Int = {
    println("call getter!");
    _id;
  }
  // setter
  def id_= (id:Int) = {
    println("call setter!");
    _id = id;
  }
}

scala> val hoge = new SimpleClass3
hoge: SimpleClass3 = SimpleClass3@16becf68

scala> hoge.id = 3
call setter!
call getter!
hoge.id: Int = 3

scala> hoge.id_=(999)
call setter!

scala> hoge.id
call getter!
res1: Int = 999

継承

シングルトン

コンパニオンオブジェクト

ケースクラス

32
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
25