Jawaban:
Java mendukung * tipe kembali kovarian untuk metode ditimpa. Ini berarti metode yang diganti mungkin memiliki tipe pengembalian yang lebih spesifik. Yaitu, selama tipe pengembalian baru dapat ditetapkan untuk jenis kembali metode yang Anda timpa, itu diperbolehkan.
Sebagai contoh:
class ShapeBuilder {
...
public Shape build() {
....
}
class CircleBuilder extends ShapeBuilder{
...
@Override
public Circle build() {
....
}
Ini ditentukan dalam bagian 8.4.5 dari Spesifikasi Bahasa Jawa :
Jenis kembali dapat bervariasi antara metode yang menimpa satu sama lain jika jenis kembali adalah jenis referensi. Gagasan pengembalian-jenis-substitusi mendukung pengembalian kovarian, yaitu, spesialisasi jenis kembali ke subtipe.
Deklarasi metode d1 dengan tipe kembali R1 adalah tipe-kembali-dapat diganti untuk metode lain d2 dengan tipe kembali R2, jika dan hanya jika kondisi berikut ini berlaku:
Jika R1 batal maka R2 batal.
Jika R1 adalah tipe primitif, maka R2 identik dengan R1.
Jika R1 adalah tipe referensi, maka:
R1 adalah subtipe R2 atau R1 dapat dikonversi ke subtipe R2 dengan konversi yang tidak dicentang (§5.1.9), atau
R1 = | R2 |
("| R2 |" mengacu pada penghapusan R2, sebagaimana didefinisikan dalam §4.6 dari JLS .)
* Sebelum Java 5, Java memiliki tipe-tipe return yang invarian , yang berarti tipe return dari metode override yang diperlukan agar sama persis dengan metode yang diganti.
Ya mungkin berbeda tetapi ada beberapa batasan.
Sebelum Java 5.0, saat Anda mengganti metode, parameter dan tipe pengembalian harus sama persis. Di Java 5.0, ia memperkenalkan fasilitas baru yang disebut tipe pengembalian kovarian. Anda bisa mengganti metode dengan tanda tangan yang sama tetapi mengembalikan subclass dari objek yang dikembalikan. Dengan kata lain, metode dalam subkelas dapat mengembalikan objek yang tipenya adalah subkelas dari jenis yang dikembalikan oleh metode dengan tanda tangan yang sama di dalam superclass.
Ya, jika mereka mengembalikan subtipe. Ini sebuah contoh:
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 {
}
}
Kode ini mengkompilasi dan menjalankan.
Secara garis besar ya jenis pengembalian metode utama bisa berbeda. Tapi itu tidak lurus ke depan karena ada beberapa kasus yang terlibat dalam hal ini.
Kasus 1: Jika tipe pengembalian adalah tipe data primitif atau batal.
Output: Jika tipe kembali batal atau primitif maka tipe data metode kelas induk dan metode utama harus sama. misalnya jika tipe pengembaliannya adalah int, float, string maka harus sama
Kasus 2: Jika tipe pengembalian adalah tipe data turunan:
Keluaran: Jika tipe kembalinya dari metode kelas induk adalah tipe turunan maka tipe kembalinya dari metode utama adalah tipe data turunan yang sama dari subkelas dengan tipe data turunan. Misalkan saya memiliki kelas A, B adalah subkelas ke A, C adalah subkelas ke B dan D adalah subkelas ke C; kemudian jika kelas super mengembalikan tipe A maka metode overriding adalah subclass dapat mengembalikan tipe A, B, C atau D yaitu sub-jenisnya. Ini juga disebut sebagai kovarians.
ya itu mungkin .. tipe pengembalian bisa berbeda hanya jika metode kelas induk jenis kembali adalah
tipe super dari jenis metode kelas anak ..
berarti
class ParentClass {
public Circle() method1() {
return new Cirlce();
}
}
class ChildClass extends ParentClass {
public Square method1() {
return new Square();
}
}
Class Circle {
}
class Square extends Circle {
}
baik, jawabannya adalah ya ... DAN TIDAK.
tergantung pertanyaannya. semua orang di sini menjawab tentang Java> = 5, dan beberapa menyebutkan bahwa Java <5 tidak memiliki tipe kovarian.
sebenarnya, spesifikasi bahasa Java> = 5 mendukungnya, tetapi runtime Java tidak. khususnya, JVM tidak diperbarui untuk mendukung tipe pengembalian kovarian.
dalam apa yang dilihat kemudian sebagai langkah "pintar" tetapi akhirnya menjadi salah satu keputusan desain terburuk dalam sejarah Jawa, Java 5 mengimplementasikan banyak fitur bahasa baru tanpa memodifikasi JVM atau spesifikasi classfile sama sekali. alih-alih semua fitur diimplementasikan dengan tipu daya di javac: kompilator menghasilkan / menggunakan kelas polos untuk kelas bersarang / bagian dalam, menghapus tipe dan gips untuk generik, pengakses sintetis untuk "persahabatan" pribadi bersarang / kelas dalam, bidang instance sintetis untuk bagian luar 'ini' pointer, bidang statis sintetik untuk literal '.class', dll., dll.
dan tipe kovarian kembali adalah gula sintaksis yang ditambahkan oleh javac.
misalnya, saat kompilasi ini:
class Base {
Object get() { return null; }
}
class Derived extends Base {
@Override
@SomeAnnotation
Integer get() { return null; }
}
javac akan menampilkan dua metode get di kelas Derived:
Integer Integer:Derived:get() { return null; }
synthetic bridge Object Object:Derived:get() { return Integer:Derived:get(); }
metode jembatan yang dihasilkan (ditandai synthetic
dan bridge
dalam bytecode) adalah apa yang sebenarnya ditimpa Object:Base:get()
karena, untuk JVM, metode dengan tipe pengembalian yang berbeda sepenuhnya independen dan tidak dapat saling menimpa. untuk memberikan perilaku yang diharapkan, jembatan hanya memanggil metode "nyata" Anda. pada contoh di atas, javac akan menjelaskan metode bridge dan real di Derived dengan @SomeAnnotation.
perhatikan bahwa Anda tidak dapat membuat kode tangan solusi ini di Java <5, karena metode jembatan dan nyata hanya berbeda dalam jenis pengembalian dan karenanya mereka tidak dapat hidup berdampingan dalam program Java. tetapi di dunia JVM, tipe metode pengembalian adalah bagian dari tanda tangan metode (seperti argumen mereka) dan kedua metode yang bernama sama dan mengambil argumen yang sama tetap dianggap sepenuhnya independen oleh JVM karena jenis pengembalian yang berbeda, dan bisa hidup berdampingan.
(BTW, jenis bidang adalah bagian yang sama dari tanda tangan bidang dalam bytecode, jadi adalah sah untuk memiliki beberapa bidang dari jenis yang berbeda tetapi dinamai sama dalam satu kelas bytecode.)
jadi untuk menjawab pertanyaan Anda sepenuhnya: JVM tidak mendukung tipe pengembalian kovarian, tetapi javac> = 5 memalsukannya pada waktu kompilasi dengan lapisan gula sintaksis manis.
Overriding dan Return Types, dan Covariant Returns
subclass harus mendefinisikan metode yang cocok dengan versi yang diwarisi dengan tepat. Atau, pada Java 5, Anda diizinkan untuk mengubah jenis pengembalian di
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, kode ini akan dikompilasi. Jika Anda mencoba untuk mengkompilasi kode ini dengan kompiler 1.4 akan mengatakan mencoba menggunakan jenis pengembalian yang tidak kompatibel - sandeep1987 1 mnt yang lalu
Jawaban lainnya semuanya benar, tetapi secara mengejutkan semua meninggalkan aspek teoritis di sini: tipe pengembalian dapat berbeda, tetapi mereka hanya dapat membatasi jenis yang digunakan dalam kelas super karena Prinsip Substitusi Liskov .
Ini sangat sederhana: ketika Anda memiliki kode "klien" yang memanggil beberapa metode:
int foo = someBar.bar();
maka hal di atas harus bekerja (dan mengembalikan sesuatu yang int
tidak peduli implementasi mana yang bar()
diminta).
Artinya: jika ada subkelas Bar yang menggantikan bar()
maka Anda masih harus mengembalikan sesuatu yang tidak merusak "kode pemanggil".
Dengan kata lain: asumsikan bahwa basis bar()
seharusnya mengembalikan int. Kemudian subkelas bisa kembalishort
- tetapi bukan long
karena penelepon akan baik-baik saja berurusan dengan short
nilai, tetapi bukan long
!
Jenis kembali harus sama dengan, atau subtipe dari, jenis kembali dinyatakan dalam metode override asli dalam superclass.
YA itu mungkin
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();
}
}
Iya. Dimungkinkan untuk metode yang diganti untuk memiliki tipe pengembalian yang berbeda.
Tetapi keterbatasannya adalah bahwa metode yang diganti harus memiliki tipe pengembalian yang lebih spesifik dari jenis kembali dari metode aktual.
Semua jawaban telah memberikan contoh metode override untuk memiliki tipe kembali yang merupakan subkelas dari tipe kembali dari metode aktual.
Sebagai contoh :
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
}
}
Tapi ini tidak hanya terbatas pada subkelas. Bahkan kelas yang mengimplementasikan antarmuka adalah tipe antarmuka tertentu dan dengan demikian dapat menjadi tipe pengembalian di mana antarmuka diharapkan.
Sebagai contoh :
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