【追記あり】Scalaのobjectとclassの違いについての雑な理解とそれに対するご指摘

Scalaのobjectとclassって何が違うのか、よくわかっていなかったのでまとめました。 追記 前半のやり取りが盛大に間違っていたのと、やり取りがたいへんわかりづらいので、がくぞ(@gakuzzzz)さんにご指摘を頂きました。
1
がくぞ @gakuzzzz

@shigemk2 ちょっと全然関係ない要素が入り乱れまくって意味不明な会話になってる気がします……。

2015-10-10 19:08:52
shigemk2 @shigemk2

@gakuzzzz すみません。一つ一つ理解しようと思って色々質問してたら、話が拡散してしまいました。Function1のくだりは直接関係ないのにそのあたりについても質問してしまったので、端から見たら追いかけづらい会話になってしまってます。

2015-10-10 19:11:37
がくぞ @gakuzzzz

@shigemk2 というよりも無駄に複雑に理解してる気がしており、一旦先の会話は忘れた方がよさそうな気がします

2015-10-10 19:15:20
shigemk2 @shigemk2

@gakuzzzz やはり理解の仕方が複雑でしょうか?

2015-10-10 19:21:11
がくぞ @gakuzzzz

@shigemk2 というよりも shigemk2.com/entry/scala_ob… 記事読む限り間違いだらけですね。

2015-10-10 19:21:55
がくぞ @gakuzzzz

@shigemk2 いや、正しい所もありますが、なんか無駄に関係無いものをごっちゃにして複雑にしている印象が……

2015-10-10 19:23:13
shigemk2 @shigemk2

@gakuzzzz ご指摘ありがとうございます。後学のために、どこが間違っててどこが正しいのか教えて頂けますでしょうか。お手数おかけします。

2015-10-10 19:25:34
がくぞ @gakuzzzz

@shigemk2 まず、class は型を定義するもので object は値を定義するもので全く違う構文です。 意味合い的に object Foo とすると val Foo = new AnyRef { } に近い意味になります(厳密には違いますが)

2015-10-10 19:26:41
がくぞ @gakuzzzz

@shigemk2 class Foo とすると 型Foo ができて、val Bar = new Foo とするとfooという変数にFoo型の値が代入されます。 object Foo とすると、 Fooという変数にFoo.type型の値が代入されます。た

2015-10-10 19:31:00
がくぞ @gakuzzzz

@shigemk2 本来、Foo型と Foo.type型は違う型です。なのでFoo型にprivateなメンバが存在していても、Foo.type からはそのメンバにはアクセスする事ができません。しかしclass Fooとobject Fooが同一のファイルに定義されていたとき

2015-10-10 19:32:59
がくぞ @gakuzzzz

@shigemk2 その両者は特別な関係を持ち、両者のprivateなメンバにアクセスできるという特例が与えられます。この関係をさして、object Fooはclass Fooのコンパニオンオブジェクト、class Fooはobject Fooのコンパニオンクラスと言います

2015-10-10 19:34:34
がくぞ @gakuzzzz

@shigemk2 で、case class Foo() とすると、自分で書かなくても自動的にobject Fooが定義され、いくつかのメソッドがFoo型とFoo.type型に定義されます。この際、Foo.type型はFunctionNのサブクラスになっています。

2015-10-10 19:37:32
がくぞ @gakuzzzz

@shigemk2 また、case class Foo() を定義した際に、明示的に自分で object Foo を定義する事も可能です。その場合は同様にFoo.type型にいくつかのメソッドが自動で定義されます。ただしその場合、

2015-10-10 19:40:00
shigemk2 @shigemk2

@gakuzzzz なので、case classもobjectもコンパニオンオブジェクトと呼ばれるのですね。先の例に則ると、class Fooのコンパニオンオブジェクトに。

2015-10-10 19:40:09
がくぞ @gakuzzzz

@shigemk2 明示的にobject Foo extends Function1[String, Foo] などと書かない限り、Foo.typeはFunctionNのサブクラスにはなりません。

2015-10-10 19:40:38
がくぞ @gakuzzzz

@shigemk2 「case classもobjectもコンパニオンオブジェクトと呼ばれる」 そんな事実は無いです。

2015-10-10 19:41:26
がくぞ @gakuzzzz

@shigemk2 case class を定義すると自動的にコンパニオンオブジェクトが定義される、というだけで case classをコンパニオンオブジェクトと呼ぶのは明確に間違いです

2015-10-10 19:42:14
がくぞ @gakuzzzz

@shigemk2 またobjectも同名のclassが存在しているのであればそのclassのコンパニオンオブジェクトと呼ぶことはできますが、同名のクラスが無い場合にコンパニオンオブジェクトと呼ぶのは間違いです。

2015-10-10 19:44:25
shigemk2 @shigemk2

@gakuzzzz 色々とありがとうございます。無理くりclassとobjectとcase classをコンパニオンオブジェクトという言葉でもって同一視したのが間違いのようです。

2015-10-10 20:08:41
がくぞ @gakuzzzz

@shigemk2 はい。あくまでコンパニオンオブジェクトはobjectが特定の条件を満たした場合に、コンパニオンオブジェクトとも呼べるというだけですね。

2015-10-10 20:11:53
shigemk2 @shigemk2

@gakuzzzz 前提として、当たり前ですが、objectとclassは全くの別物、というところから始めないといけない理解です。

2015-10-10 20:14:57
func @func_hs

@shigemk2 @gakuzzzz ありゃ、的はずれな回答でしたか。申し訳ない><

2015-10-10 20:15:31
shigemk2 @shigemk2

@gakuzzzz @func_hs 件のブログ記事ですが、要点1と2はともかく、要点3は後から読んで本当に意味不明でした。 shigemk2.com/entry/scala_ob…

2015-10-10 20:20:08