Scalaが難しいので初歩の初歩からやり直すことにした(その2)

object HelloWorld {
  def main(args: Array[String]): Unit = {
    System.out.println("Hello, Scala!")
  }
}

一行目

object HelloWorld {
  • 「object」ってなんだ?! 「class」じゃないのか?!

object [オブジェクト名] って書くと、まずシングルトンなクラスを定義してくれて、おまけにインスタンスの生成までやってくれる。
[オブジェクト名]はオブジェクトのように扱うことができる。スゴイ。オブジェクトそのものなんだから『オブジェクトのように』っていう表現はおかしいな。変数のように扱うことができる。
不変オブジェクト(『定数』と呼ぶべきか)になって再代入はできない。
でも再定義はできる。再定義を禁止する方法はないのかな?

  • 「public」はいらないのか?!

オブジェクト定義の頭に「public」ってつけると怒られる。「protected」と「private」は怒られない。Javaのクラス定義とは真逆。
「protected」ってつけても、「private」ってつけても、あるいは何もつけなくても、他のところから普通に見えてしまう。これは面妖な。

色々やってみた結果

オブジェクト定義(クラス定義ではない)

scala> object obj {
     |   var id = 0
     |   var name = "no name"
     |   def sayName = {
     |     System.out.println( "My name is " + name );
     |   }
     | }
defined module obj

モジュール?


変数と同じように扱える

scala> System.out.println( obj )
line1$object$$iw$$iw$obj$@1a40fff

scala> System.out.println( obj.getClass )
class line1$object$$iw$$iw$obj$

scala> System.out.println( obj.toString )
line1$object$$iw$$iw$obj$@1a40fff

scala> System.out.println( obj.id )
0

scala> System.out.println( obj.name )
no name

scala> obj.sayName
My name is no name


プロパティに値を設定できる

scala> obj.id = 1
scala> obj.name = "syttru"

scala> System.out.println( obj.id )
1

scala> System.out.println( obj.name )
syttru

scala> obj.sayName
My name is syttru


シングルトンかつ不変

scala> obj = 1
<console>:7: error: assignment to immutable value ( 不変の値に代入するんじゃない! )
       obj = 1
           ^


他の変数に代入することはできる

scala> var a = obj
a: object obj = obj$@1a40fff

scala> a.sayName
My name is syttru

再定義されたら変わっちゃう

scala> var obj = 1
obj: Int = 1

scala> System.out.println( obj )
1


「public」とか「protected」とか「private」とかつけてみた

scala> public object publicObj
error: That kind of statement combination is not supported by the interpreter.
       ( その種類の文の組み合わせはインタプリタによってサポートされません。 )

scala> protected object protectedObj
defined module protectedObj

scala> private object privateObj
defined module privateObj

インタープリターだからダメなのかな


じゃあコンパイルしてみよう

// public_object.scala

// publicなオブジェクト
public object publicObj
// protected_object.scala

// protected なオブジェクト
protected object protectedObj
// nomodifier_object.scala

// 無印なオブジェクト
object nomodifierObj
// private_object.scala

// private なオブジェクト
private object privateObj


のーみそこねこねコンパイル

$ scalac public_object.scala
public_object.scala:4: error: expected class or object definition
                              ( 予想されたクラスかオブジェクト定義 ) ??? わからん! 英語キライ
public object publicObj
^
one error found
$ scalac protected_object.scala
$ scalac nomodifier_object.scala
$ scalac private_object.scala

やっぱり「public」だけが怒られる。出てくるエラーメッセージも、エキサイト翻訳だけが頼りの私には難しすぎる。


そもそもこれらはホントにスコープ修飾子なのか?
他のオブジェクトから参照してみよう。

// main.scala

object main {
  def main(args: Array[String]) {
    System.out.println( privateObj )
    System.out.println( protectedObj )
    System.out.println( nomodifierObj )
  }
}
$ scalac main.scala
$ scala main
privateObj$@5e0602
protectedObj$@1621e42
nomodifierObj$@1787038

全て正常にコンパイルして実行できた。うーむ。謎だ。