戻り値の型が明示的に指定されていない場合、Unitを返すメソッドをStringを返すメソッドでオーバーライドできるのはなぜですか?


11

私はScala Edition1のプログラミングにおける特性の章のコード例を通して作業していました https://www.artima.com/pins1ed/traits.html

そして私のタイプミスのために奇妙な行動に出くわしました。以下の特性のオーバーライドメソッドでは、コードスニペットではコンパイルエラーは発生しませんが、オーバーライドされたメソッドの戻り値の型はUnitvs とは異なりStringます。しかし、オブジェクトのメソッドを呼び出すと、Unitが返されますが、何も出力されません。

trait Philosophical {
    def philosophize = println("I consume memory, therefore I am!")
}

class Frog extends Philosophical {
  override def toString = "green"
  override def philosophize = "It aint easy to be " + toString + "!"
}

val frog = new Frog
//frog: Frog = green

frog.philosophize
// no message printed on console

val f = frog.philosophize
//f: Unit = ()

しかし、オーバーライドされたメソッドで明示的な戻り値の型を指定すると、コンパイルエラーが発生します。

class Frog extends Philosophical {
  override def toString = "green"
  override def philosophize: String = "It aint easy to be " + toString + "!"
}
         override def philosophize: String = "It aint easy to be " + toString +
                      ^
On line 3: error: incompatible type in overriding
       def philosophize: Unit (defined in trait Philosophical);
        found   : => String
        required: => Unit

最初のケースでコンパイルエラーがない理由を誰かが説明するのを手伝ってくれる?


コンパイラは、異なる結果タイプを持つメソッドをオーバーライドしようとする有効なヒントを出力しました。
Andriy Plokhotnyuk

はい、確かに、しかし私の質問は、なぜそれが最初のケースでコンパイラを通過したのか
Shanil

1
経験則として、戻り値の型については常に明確にしてください_(特にパブリックAPIの場合)_。型推論はローカル変数に最適です。
Luis MiguelMejíaSuárez19年

回答:



6

私の質問は、なぜそれが最初のケースでコンパイラを通過したのかです

戻り値の型を明示的に指定しなかった場合、overrideが機能するために必要な型によって推測されました。

それが判明したUnit

String値(関数本体を構成する式の値)を割り当てることができるのでUnit、コンパイラーは満足です。


1
ただし、ここで知りたいのは、明示的な戻り値の型Stringが拒否された理由です。Javaでは(そして私はScalaでもそうだと思います)、オーバーライドするときに戻り値の型を狭めることができます。たとえば、親メソッドがを返すとNumber、を返すことができますInteger。多分void/ Unit特別です。
Thilo、

1
例えばこのコンパイル、:trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
ティロ

2
戻り値の型をサブタイプに絞り込むことができます。ただし、オーバーライドされたメソッドの戻り値の型に暗黙的に変換できる型に限定することはできません。Stringto Unitは2番目のものに似ていますが、厳密にはそうではありません。
Alexey Romanov

2
バイトコードレベルでは何の狭小化の戻り値の型は、2つの方法で実際に存在し、どちらかありませんFrogdef philosophize : Integerとはdef philosophize : Number。2番目Philosophicalのメソッドは実際にのメソッドをオーバーライドします(最初のメソッドを呼び出します)。同じことが確かにvoid他のすべてのことに対して行われる可能性があります。
Alexey Romanov

2
1. Javaも同じです。2.はい、バイトコードでできます。たとえば、stackoverflow.com / questions / 18655541 / およびstackoverflow.com/questions/58065680/…を参照してください。
Alexey Romanov
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.