回答:
Javaは、オーバーライドされたメソッドの*共変の戻り値型をサポートします。これは、オーバーライドされたメソッドがより具体的な戻り値の型を持つ可能性があることを意味します。つまり、オーバーライドするメソッドの戻り値の型に新しい戻り値の型を割り当てることができる限り、許可されます。
例えば:
class ShapeBuilder {
...
public Shape build() {
....
}
class CircleBuilder extends ShapeBuilder{
...
@Override
public Circle build() {
....
}
これは、Java言語仕様のセクション8.4.5で指定されています。
戻り値の型が参照型である場合、戻り値の型は、互いにオーバーライドするメソッド間で異なる場合があります。return-type-subsututabilityの概念は、共変の戻り値、つまり戻り値の型からサブタイプへの特殊化をサポートしています。
戻り型R1のメソッド宣言d1は、戻り型R2の別のメソッドd2の戻り型置換可能です。ただし、次の条件が当てはまる場合に限ります。
R1が無効の場合、R2も無効になります。
R1がプリミティブ型の場合、R2はR1と同じです。
R1が参照型の場合:
R1がR2のサブタイプであるか、R1がチェックされていない変換(§5.1.9)によってR2のサブタイプに変換できる、または
R1 = | R2 |
(「| R2 |」は、JLSの4.6で定義されているR2の消去を指します。)
* Java 5より前は、Javaには不変の戻り型がありました。つまり、オーバーライドされるメソッドと正確に一致するために必要なメソッドオーバーライドの戻り型がありました。
はい、サブタイプを返す場合。次に例を示します。
package com.sandbox;
public class Sandbox {
private static class Parent {
public ParentReturnType run() {
return new ParentReturnType();
}
}
private static class ParentReturnType {
}
private static class Child extends Parent {
@Override
public ChildReturnType run() {
return new ChildReturnType();
}
}
private static class ChildReturnType extends ParentReturnType {
}
}
このコードはコンパイルして実行されます。
大まかに言えば、オーバーライドメソッドの戻り値の型は異なる場合があります。しかし、これにはいくつかのケースが関与しているため、簡単ではありません。
ケース1:戻り値の型がプリミティブデータ型またはvoidの場合。
出力:戻り値の型がvoidまたはプリミティブの場合、親クラスのメソッドとオーバーライドするメソッドのデータ型は同じである必要があります。たとえば、戻り値の型がint、float、stringの場合、それは同じである必要があります
ケース2:戻り型が派生データ型の場合:
出力:親クラスのメソッドの戻り値の型が派生型の場合、オーバーライドするメソッドの戻り値の型は、サブクラスの派生データ型と派生データ型と同じです。たとえば、クラスAがあり、BがAのサブクラス、CがBのサブクラス、DがCのサブクラスであるとします。スーパークラスがタイプAを返す場合、オーバーライドするメソッドはサブクラスであり、A、B、C、またはDタイプ、つまりそのサブタイプを返すことができます。これは共分散とも呼ばれます。
はい、親クラスのメソッドの戻り値の型がある場合にのみ..戻り型が異なることが可能です
。..子クラスのメソッドの戻り値の型のスーパータイプは、
手段
class ParentClass {
public Circle() method1() {
return new Cirlce();
}
}
class ChildClass extends ParentClass {
public Square method1() {
return new Square();
}
}
Class Circle {
}
class Square extends Circle {
}
ええ、答えはイエスです...そしてノーです。
質問によって異なります。Java> = 5に関してここで全員が回答し、Java <5は共変の戻り値型を備えていないと述べた人もいます。
実際、Java言語仕様> = 5ではサポートされていますが、Javaランタイムではサポートされていません。特に、JVMは共変の戻り値の型をサポートするように更新されていません。
「賢い」動きと見なされていたものの、Javaの歴史の中で最悪の設計決定の1つとなったJava 5は、JVMやクラスファイルの仕様をまったく変更することなく、一連の新しい言語機能を実装しました。代わりに、すべての機能がjavacで巧妙に実装されました:コンパイラーは、ネストされた/内部クラスのプレーンクラス、ジェネリックの型消去とキャスト、ネストされた/内部クラスの合成アクセサー、プライベート「フレンドシップ」、外部「this」の合成インスタンスフィールドを生成/使用しますポインタ、「。class」リテラルの合成静的フィールドなど
また、共変の戻り値型は、javacによって追加された構文糖衣です。
たとえば、これをコンパイルする場合:
class Base {
Object get() { return null; }
}
class Derived extends Base {
@Override
@SomeAnnotation
Integer get() { return null; }
}
javacは、Derivedクラスの2つのgetメソッドを出力します。
Integer Integer:Derived:get() { return null; }
synthetic bridge Object Object:Derived:get() { return Integer:Derived:get(); }
生成されたブリッジメソッド(マークさsynthetic
れbridge
、バイトコード)はObject:Base:get()
、JVMに対して、戻り値の型が異なるメソッドは完全に独立しており、互いにオーバーライドできないため、実際にオーバーライドされます。期待される動作を提供するために、ブリッジは単に「実際の」メソッドを呼び出します。上記の例では、javacは@SomeAnnotationでDerivedのブリッジメソッドと実際のメソッドの両方に注釈を付けます。
ブリッジと実際のメソッドは戻り値の型のみが異なり、したがってJavaプログラム内で共存できないため、Java 5未満ではこのソリューションを手動でコーディングできないことに注意してください。ただし、JVMの世界では、メソッドの戻り値の型はメソッドシグネチャの一部であり(引数と同様)、同じ名前で同じ引数を取る2つのメソッドは、戻り値の型が異なるため、JVMから完全に独立していると見なされます。そして共存することができます。
(ところで、フィールドのタイプはバイトコードのフィールドシグネチャの一部であるので、単一のバイトコードクラス内で異なるタイプの複数のフィールドに同じ名前を付けることは合法です。)
だからあなたの質問に完全に答えるために:JVMは共変の戻り型をサポートしていませんが、javac> = 5はコンパイル時に甘い構文糖のコーティングでそれを偽ります。
オーバーライド型と戻り型、および共変戻り値
サブクラスは、継承されたバージョンと正確に一致するメソッドを定義する必要があります。または、Java 5以降では、戻り値の型を
class Alpha {
Alpha doStuff(char c) {
return new Alpha();
}
}
class Beta extends Alpha {
Beta doStuff(char c) { // legal override in Java 1.5
return new Beta();
}
} }
Java 5、このコードはコンパイルされます。このコードを1.4コンパイラでコンパイルしようとすると、互換性のない戻り値の型を使用しようとすると表示されます– sandeep1987 1分前
他の答えはすべて正解ですが、驚くべきことに、ここでは理論的な側面をすべて省略しています。戻り値の型は異なる場合がありますが、スーパークラスで使用される型を制限できるのは、リスコフの置換原理のためです。
それは非常に単純です:いくつかのメソッドを呼び出す「クライアント」コードがある場合:
int foo = someBar.bar();
次に、上記は機能する必要int
がbar()
あります(呼び出される実装に関係なく何かを返す必要があります)。
意味:オーバーライドするBarサブクラスがあるbar()
場合でも、「呼び出し元コード」を壊さない何かを返す必要があります。
つまり、ベースbar()
がintを返すことになっていると仮定します。次に、サブクラスが戻る可能性short
がありますがlong
、呼び出し元はshort
値を正しく処理しますが、long
!
戻りの型は、スーパークラスの元のオーバーライドされたメソッドで宣言された戻りの型と同じか、そのサブタイプである必要があります。
はい、可能です
class base {
base show(){
System.out.println("base class");
return new base();
}
}
class sub extends base{
sub show(){
System.out.println("sub class");
return new sub();
}
}
class inheritance{
public static void main(String []args) {
sub obj=new sub();
obj.show();
}
}
はい。オーバーライドされたメソッドが異なる戻り値の型を持つ可能性があります。
しかし、制限は、オーバーライドされたメソッドが、実際のメソッドの戻り型のより具体的な型である戻り型を持つ必要があることです。
すべての回答には、オーバーライドされたメソッドの例があり、実際のメソッドの戻り型のサブクラスである戻り型を持っています。
例えば :
public class Foo{
//method which returns Foo
Foo getFoo(){
//your code
}
}
public class subFoo extends Foo{
//Overridden method which returns subclass of Foo
@Override
subFoo getFoo(){
//your code
}
}
ただし、これはサブクラスだけに限定されているわけではありません。インターフェイスを実装するクラスでも、特定のタイプのインターフェイスであるため、インターフェイスが期待される戻り値の型になる場合があります。
例えば :
public interface Foo{
//method which returns Foo
Foo getFoo();
}
public class Fizz implements Foo{
//Overridden method which returns Fizz(as it implements Foo)
@Override
Fizz getFoo(){
//your code
}
}
class Phone {
public Phone getMsg() {
System.out.println("phone...");
return new Phone();
}
}
class Samsung extends Phone{
@Override
public Samsung getMsg() {
System.out.println("samsung...");
return new Samsung();
}
public static void main(String[] args) {
Phone p=new Samsung();
p.getMsg();
}
}
error: method() in subclass cannot override method() in superclass