Java'da neden birden fazla kalıtım yoktur, ancak birden çok arabirimin uygulanmasına izin verilir?


153

Java birden fazla kalıtıma izin vermez, ancak birden fazla arabirimin uygulanmasına izin verir. Neden?


1
Daha açıklayıcı olması için soru başlığını düzenledim.
Bozho

4
İlginç bir şekilde, JDK 8'de, arayüz yöntemlerinin uygulanmasının tanımlanmasına izin verecek uzantı yöntemleri olacaktır. Kurallar, davranışların birden fazla mirasını yönetmek için tanımlanmıştır, ancak devleti değil (ki bu daha problemlidir .
Edwin Dalorzo

1
Siz sadece "Java birden fazla mirasa nasıl erişir" diyen cevaplar için zaman kaybetmeden önce ... Bu doğru sınıflara izin vermemek için, mantıksal olarak size dahili olarak olması gerekenleri veren @Prabal Srivastava cevabına gitmenizi öneririm. ve yalnızca arabirimlere birden fazla kalıtım izni verme hakkına izin verin.
Yo Apps

Yanıtlar:


228

Arabirimler sadece belirtmek Çünkü neyi sınıf değildir, yapıyor nasıl bunu yapıyor.

Çoklu kalıtımla ilgili sorun, iki sınıfın aynı şeyi yapmanın farklı yollarını tanımlayabilmesidir ve alt sınıf hangisini seçeceğini seçemez.


8
Eskiden C ++ yapıyordum ve aynı sorunla birkaç kez karşılaştım. Geçenlerde Scala hakkında bana "C ++" yolu ve "Java" yolu şeyler arasında bir şey gibi görünen "özellikleri" olan hakkında okuyun.
Niels Basjes

2
Bu şekilde, "elmas probleminden" kaçınıyorsunuz: en.wikipedia.org/wiki/Diamond_problem#The_diamond_problem
Nick L.

6
Java 8'den beri her arabirimde bir tane olmak üzere iki özdeş varsayılan yöntem tanımlayabilirsiniz. Sınıfınızda her iki arabirimi de uygulayacaksanız, sınıfın kendisinde bu yöntemi geçersiz kılmalısınız
bobbel

6
Bu cevap doğru değil. Sorun nasıl ve Java 8'in kanıtlamak için orada olduğunu belirtmemek . Java 8'de, iki süper arabirim aynı yöntemi farklı uygulamalarla bildirebilir, ancak bu bir sorun değildir, çünkü arabirim yöntemleri sanaldır , böylece bunların üzerine yazabilirsiniz ve sorun çözülür. Asıl sorun hakkındadır belirsizlik içinde nitelikler Eğer özellik (nitelikler sanal değildir) üzerine yazarak bu belirsizlik çözemez çünkü.
Alex Oliveira

1
"Nitelikler" ile ne demek istiyorsun?
Bozho

96

Üniversite eğitmenlerimden biri bana şöyle açıkladı:

Bir Toaster olan bir sınıfım ve NuclearBomb olan başka bir sınıfım olduğunu varsayalım. İkisinin de bir "karanlık" ayarı olabilir. Her ikisinin de on () yöntemi vardır. (Birinin bir off () vardır, diğeri yoktur.) Bunların her ikisinin de bir alt sınıfı olan bir sınıf oluşturmak istersem ... gördüğünüz gibi, bu gerçekten yüzümde patlayabilecek bir sorun .

Yani ana konulardan biri, iki ana sınıfınız varsa, aynı özelliğin farklı uygulamalarına sahip olabilirler - veya eğitmenimin örneğindeki gibi aynı ada sahip iki farklı özelliğe sahip olabilirler. O zaman alt sınıfınızın hangisini kullanacağına karar vermek zorundasınız. Bunu ele almanın yolları var, kesinlikle - C ++ bunu yapıyor - ancak Java tasarımcıları bunun çok karmaşık olacağını düşünüyor.

Bununla birlikte, bir arayüzle, başka bir sınıfın bir şey yapma yöntemini ödünç almak yerine sınıfın yapabileceği bir şeyi açıklıyorsunuz. Birden çok arabirimin, çözülmesi gereken zor çakışmalara neden olması, birden çok üst sınıftan daha az olasıdır.


5
Teşekkürler, NomeN. Sözün kaynağı, aynı zamanda açık kaynaklı Quake 2 kaynak deposunun koruyucusu olan Brendan Burns adında bir doktora öğrencisiydi. Git şekil.
Sözdizimsel

4
Bu benzetmenin sorunu, bir nükleer bomba ve bir ekmek kızartma makinesinin bir alt sınıfını oluşturuyorsanız, "nükleer ekmek kızartma makinesi" kullanıldığında makul bir şekilde patlayacaktır.
101100

20
Birisi nükleer bomba ve ekmek kızartma makinesini karıştırmaya karar verirse, bombanın yüzüne patlamasını hak eder. Alıntı yanlış bir muhakeme
masoud

1
Aynı programlama dili çoklu "arayüz" kalıtımına izin verir, bu nedenle bu "gerekçe" geçerli değildir.
curiousguy

24

Kalıtım sen bile fazla kullanılırsa Çünkü olamaz demek "Hey, yöntem yararlıdır görünüyor, ben de bu sınıfı genişletir edeceğiz".

public class MyGodClass extends AppDomainObject, HttpServlet, MouseAdapter, 
             AbstractTableModel, AbstractListModel, AbstractList, AbstractMap, ...

Mirasın neden aşırı kullanıldığını söyleyebilir misin? Bir tanrı sınıfı yaratmak tam olarak yapmak istediğim şey! Statik yöntemlere sahip "Araçlar" sınıfları oluşturarak tek miras etrafında çalışan pek çok insan buluyorum.
Duncan Calvert

9
@DuncanCalvert: Hayır, bunu yapmak istemezsiniz, bu kodun bakıma ihtiyacı olursa. Birçok statik yöntem OO'nun noktasını kaçırır, ancak aşırı çoklu kalıtım çok daha kötüdür, çünkü hangi kodun nerede kullanıldığını ve bir sınıfın kavramsal olarak ne olduğunu tamamen kaybedersiniz. Her ikisi de "bu kodu ihtiyacım olan yerde nasıl kullanabilirim" sorununu çözmeye çalışıyorsunuz, ancak bu kısa vadeli basit bir sorundur. Uygun OO tasarımı ile çözülen çok daha zor uzun vadeli sorun "program 20 öngörülemez şekilde 20 farklı yerde kırılmadan bu kodu nasıl değiştirebilirim?
Michael Borgwardt

2
@DuncanCalvert: ve bunu yüksek uyum ve düşük kuplajlı sınıflara sahip olarak çözüyorsunuz, bu da birbirleriyle yoğun bir şekilde etkileşime giren, ancak programın geri kalanıyla yalnızca küçük, basit bir API aracılığıyla etkileşime giren veri ve kod parçaları içerdikleri anlamına geliyor. Daha sonra, iç ayrıntılar yerine bu API açısından düşünebilirsiniz, bu önemlidir, çünkü insanlar aynı anda yalnızca sınırlı miktarda ayrıntıyı akılda tutabilirler.
Michael Borgwardt

18

Bu sorunun cevabı, java derleyicisinin iç çalışmasında yatıyor (oluşturucu zinciri). Java derleyicisinin dahili çalışmasını görürsek:

public class Bank {
  public void printBankBalance(){
    System.out.println("10k");
  }
}
class SBI extends Bank{
 public void printBankBalance(){
    System.out.println("20k");
  }
}

Bu derlemeden sonra şöyle görünür:

public class Bank {
  public Bank(){
   super();
  }
  public void printBankBalance(){
    System.out.println("10k");
  }
}
class SBI extends Bank {
 SBI(){
   super();
 }
 public void printBankBalance(){
    System.out.println("20k");
  }
}

sınıfı genişletip onun bir nesnesini yarattığımızda, bir kurucu zincir Objectsınıfa kadar çalışır .

Yukarıdaki kod iyi çalışır. ancak, adı verilen başka bir sınıfımız ve Carşu adla adlandırılan Bankbir karma (çoklu kalıtım) sınıfı varsa SBICar:

class Car extends Bank {
  Car() {
    super();
  }
  public void run(){
    System.out.println("99Km/h");
  }
}
class SBICar extends Bank, Car {
  SBICar() {
    super(); //NOTE: compile time ambiguity.
  }
  public void run() {
    System.out.println("99Km/h");
  }
  public void printBankBalance(){
    System.out.println("20k");
  }
}

Bu durumda (SBICar) yapıcı zinciri oluşturamaz ( derleme zamanı belirsizliği ).

Arabirimler için buna izin verilir, çünkü onun bir nesnesini oluşturamayız.

Yeni konsept defaultve staticyöntem için lütfen arayüzde varsayılana bakın .

Umarım bu sorunuzu çözer. Teşekkürler.


7

Birden çok arayüz uygulamak çok faydalıdır ve dil uygulayıcılarına veya programcılara fazla sorun yaratmaz. Böylece izin verilir. Çoklu kalıtım da faydalı olsa da, kullanıcılara ciddi sorunlara neden olabilir (korkunç ölüm elması ). Ve çoklu kalıtımla yaptığınız çoğu şey kompozisyon veya iç sınıflar kullanılarak da yapılabilir. Dolayısıyla, birden fazla mirasın kazançlardan daha fazla sorun getirmesi yasaktır.


"Ölüm elması" ile ilgili sorun nedir?
curiousguy

2
@curiousguy Aynı temel sınıftan birden fazla alt nesne, belirsizlik (temel sınıf kullanımının geçersiz kılınması), bu belirsizliği çözmek için karmaşık kurallar içerir.
Tadeusz Kopec

@curiousguy: Bir çerçeve, bir taban türü başvurusuna bir nesne başvurusu yapmanın kimlik koruması olmasını sağlarsa, her nesne örneğinin herhangi bir temel sınıf yönteminin tam olarak bir uygulaması olmalıdır. Eğer ToyotaCarve HybridCarher ikisi de türetilmiş Carve geçersiz kılınmışsa ve her ikisi de miras alınmış ancak geçersiz kılmamışsa Car.Drive, sistemin sanalın ne yapması gerektiğini belirleyemez. Arabirimler yukarıdaki italik durumdan kaçınarak bu sorunu önler. PriusCarDriveCar.Drive
Supercat

1
@supercat "Sistemin sanal Car.Drive'ın ne yapması gerektiğini tanımlaması mümkün olmaz." <- Veya sadece bir derleme hatası verebilir ve C ++ gibi açık bir tane seçmenize neden olabilir.
Chris Middleton

1
@ChrisMiddleton: Bir yöntem void UseCar(Car &foo); arasındaki anlam ayrımı dahil etmek beklenemez ToyotaCar::Driveve HybridCar::Drive(o diğer türleri bile genellikle ne bilmeli beri ne de bakımı var ). Bir dil, C ++ 'ın yaptığı gibi, ToyotaCar &myCaronu geçmek isteyen kodun UseCarönce HybridCarveya birine yayınlanmasını gerektirebilir ToyotaCar, ancak ((Araba) (HybridCar) myCar) .Drive` olduğundan ve ((Car)(ToyotaCar)myCar).Drive farklı şeyler yapacağından kimlik koruyucu değildi.
supercat

6

Bu sorgu için doğru cevabı çoklu miras hakkındaki oracle dokümantasyon sayfasında bulabilirsiniz

  1. Birden çok durum mirası: Alanları birden çok sınıftan devralma yeteneği

    Java programlama dilinin birden fazla sınıfı genişletmenize izin vermemesinin bir nedeni, birden fazla sınıftan alan devralma yeteneği olan çoklu durum miras sorunlarından kaçınmaktır

    Birden fazla devralmaya izin verilirse ve bu sınıfı örnekleyerek bir nesne oluşturduğunuzda, bu nesne sınıfın tüm üst sınıflarından alanlarını devralır. İki soruna neden olacaktır.

    1. Farklı süper sınıflardan yöntemler veya yapıcılar aynı alanı başlatırsa ne olur?
    2. Hangi yöntem veya kurucu öncelikli olacak?
  2. Birden çok uygulama devralma: Birden çok sınıftan yöntem tanımlarını devralma yeteneği

    Bu yaklaşımla ilgili sorunlar: çatışmaları ve belirsizliği adlandırın . Bir alt sınıf ve üst sınıf aynı yöntem adını (ve imzasını) içeriyorsa, derleyici hangi sürümü çağıracağını belirleyemez.

    Ancak java, Java 8 sürümünden beri tanıtılan varsayılan yöntemlerle bu tür çoklu kalıtım türlerini destekler . Java derleyicisi, belirli bir sınıfın hangi varsayılan yöntemi kullandığını belirlemek için bazı kurallar sağlar.

    Elmas probleminin çözümü hakkında daha fazla bilgi için aşağıdaki SE yazısına bakın:

    Java 8'deki soyut sınıflar ve arayüzler arasındaki farklar nelerdir?

  3. Birden fazla tür mirası: Bir sınıfın birden fazla arabirim uygulama yeteneği.

    Arayüz değiştirilebilir alanlar içermediğinden, burada çoklu durum mirasından kaynaklanan sorunlar hakkında endişelenmenize gerek yoktur.



4

Java, yalnızca arabirimler aracılığıyla birden fazla kalıtımı destekler. Sınıf herhangi bir sayıda arabirim uygulayabilir, ancak yalnızca bir sınıfı genişletebilir.

Ölümcül elmas sorununa yol açtığı için çoklu kalıtım desteklenmez. Bununla birlikte, çözülebilir, ancak karmaşık bir sisteme yol açar, bu nedenle Java kurucuları tarafından birden fazla miras bırakılır.

Şubat 1995'te James Gosling'in “Java: Genel Bakış” başlıklı beyaz kitabında ( link ), Java'da çoklu kalıtımın neden desteklenmediği hakkında bir fikir verilmektedir.

Gosling'e göre:

"JAVA, C ++ 'ın deneyimlerimize faydadan daha fazla keder getiren nadiren kullanılan, az anlaşılmış, kafa karıştırıcı birçok özelliği atlıyor. Bu öncelikle operatör aşırı yüklemesi (yöntem aşırı yüklemesine rağmen), çoklu kalıtım ve kapsamlı otomatik zorlamalardan oluşuyor."


bağlantıya erişilemiyor. Lütfen kontrol edin ve güncelleyin.
MashukKhan

3

Aynı nedenden ötürü C #, birden fazla kalıtsallığa izin vermez, ancak birden çok arabirim uygulamanızı sağlar.

C ++ 'dan çoklu kalıtımla alınan ders, değerinden daha fazla soruna yol açmasıydı.

Arayüz, sınıfınızın uygulamak zorunda olduğu şeylerin bir sözleşmesidir. Arayüzden herhangi bir işlevsellik kazanmazsınız. Miras, bir üst sınıfın işlevselliğini miras almanıza izin verir (ve çoklu mirasta, bu son derece kafa karıştırıcı olabilir).

Birden fazla arabirime izin vermek, birden fazla kalıtım kullanarak çözebileceğiniz aynı sorunları çözmek için Tasarım Desenlerini (Adaptör gibi) kullanmanıza izin verir, ancak çok daha güvenilir ve öngörülebilir bir şekilde.


10
Java buna izin vermediğinden, C # için birden fazla devralma yoktur. Java'dan çok daha sonra tasarlandı. Bence çoklu kalıtım ile ilgili ana sorun insanların sağ ve sol kullanımı öğretildi yolu oldu. Delegasyonun çoğu durumda çok daha iyi bir alternatif olduğu kavramı doksanların başlarında ve doksanların ortasında yoktu. Bu nedenle, Araba Tekerlek ve Kapı ve Ön Cam olduğunda, Araba Tekerlekler, Kapılar ve Ön Cam içerdiğinde ders kitaplarındaki örnekleri hatırlıyorum. Java'daki tek miras, bu gerçeğe karşı diz sarsıntılı bir tepkiydi.
Alexander Pogrebnyak

2
@AlexanderPogrebnyak: Aşağıdaki üç seçenekten iki tanesini seçin: (1) Alt tip başvurusundan üst tip başvurusuna kimlik koruyucu yayınlara izin ver; (2) Bir sınıfın türetilmiş sınıfları yeniden derlemeden sanal genel üyeler eklemesine izin ver; (3) Bir sınıfın, açıkça belirtmek zorunda kalmadan sanal üyeleri birden çok temel sınıftan dolaylı olarak devralmasına izin verin. Herhangi bir dilin yukarıdakilerin üçünü de yönetmesinin mümkün olduğuna inanmıyorum. Java # 1 ve # 2'yi seçti ve C # bunu izledi. C ++ 'ın sadece # 3'ü benimsediğine inanıyorum. Şahsen, # 1 ve # 2'nin # 3'ten daha yararlı olduğunu düşünüyorum, ancak diğerleri farklı olabilir.
Supercat

@supercat "Veri üyelerinin ofsetleri derleme süresinden ziyade çalışma zamanında belirlenirse (Objective-C'nin" kırılgan olmayan ABI'larında olduğu gibi, herhangi bir dilin üçünün tümünü yönetmesinin mümkün olduğuna inanmıyorum " ") ve veya sınıf başına bir temel (yani her somut sınıfın kendi üye ofset tablosu vardır), o zaman bence 3 hedefe de ulaşılabilir.
Paramanyetik Kruvasan

@ParamagneticCroissant: Temel anlambilimsel sorun # 1. Eğer D1ve D2hem miras Bve her geçersiz kılma fonksiyonu fve eğer objbir tür bir örneği olan S, hem devralır D1ve D2ancak geçersiz kılmaz f, daha sonra bir referans döküm Siçin D1bir şey verim gereken fkullanımlar D1geçersiz kılma ve döküm Bolmamalıdır değiştir şunu. Aynı şekilde bir başvuru döküm Siçin D2olan bir şey vermelidir fkullanımları D2geçersiz kılma ve döküm Bolduğunu değiştirmemelidir. Bir dilin sanal üyelerin eklenmesine izin vermesi gerekmiyorsa ...
supercat

1
@TheParamagneticCroissant: Olabilir ve seçenekler listem bir yoruma uymak için biraz fazla basitleştirildi, ancak çalışma süresine ertelemek, D1, D2 veya S yazarının kırmadan ne gibi değişiklikler yapabileceğini bilmesini imkansız hale getiriyor sınıfının tüketicileri.
supercat

2

Bu konu yakın olmadığından bu yanıtı göndereceğim, umarım bu java'nın neden birden fazla kalıtıma izin vermediğini anlamasına yardımcı olur.

Aşağıdaki sınıfı düşünün:

public class Abc{

    public void doSomething(){

    }

}

Bu durumda Abc sınıfı hiçbir şeyi doğru uzatmıyor mu? Çok hızlı değil, bu sınıf örtük nesnesi sınıf genişletir, temel sınıf her şeyin java çalışmasına izin verir. Her şey bir nesnedir.

Eğer IDE gibi yöntemleri kullanmak için izin göreceksiniz yukarıdaki sınıfını kullanmayı denerseniz: equals(Object o), toString(), vs, ama bu yöntemleri beyan etmedi, onlar temel sınıftan çıktıObject

Deneyebilirsiniz:

public class Abc extends String{

    public void doSomething(){

    }

}

Bu iyidir, çünkü sınıfınız örtük Objectolmayacak, ancak Stringsöylediğiniz için uzayacaktır . Aşağıdaki değişikliği düşünün:

public class Abc{

    public void doSomething(){

    }

    @Override
    public String toString(){
        return "hello";
    }

}

Şimdi toString () öğesini çağırırsanız sınıfınız her zaman "merhaba" döndürür.

Şimdi aşağıdaki sınıfı hayal edin:

public class Flyer{

    public void makeFly(){

    }

}

public class Bird extends Abc, Flyer{

    public void doAnotherThing(){

    }

}

Yine sınıf Flyerörtülü yöntemi vardır Nesne uzanır toString()hepsi uzanır beri, herhangi bir sınıf bu yöntemi olacak Objectböylece, dolaylı olarak çağırırsanız, toString()gelen Birdhangi toString()kullanım olurdu java? Kimden Abcveya Flyer? Bu, iki veya daha fazla sınıfı genişletmeye çalışan herhangi bir sınıfta gerçekleşecek, bu tür "yöntem çarpışması" ndan kaçınmak için arayüz fikrini inşa ettiler , temelde onları dolaylı olarak Nesneyi dolaylı olarak genişletmeyen soyut bir sınıf olarak düşünebilirsiniz . Bunlar olduğu soyut bunlar aşağıdakilerden biri olan bir sınıfı tarafından uygulanacak gerekecektir nesne (yalnızca bir arabirimi örnekleyemezsiniz, bunlar bir sınıf tarafından uygulanmalıdır), bu yüzden her şey iyi çalışmaya devam edecektir.

Arabirimlerden sınıfları farklı için, anahtar kelime uygular sadece arayüzleri için ayrıldı.

Varsayılan olarak hiçbir şeyi genişletmediği için aynı sınıfta istediğiniz herhangi bir arabirimi uygulayabilirsiniz (ancak başka bir arabirimi genişleten bir arabirim oluşturabilirsiniz, ancak yine "baba" arabirimi Nesneyi genişletmez), bu nedenle arabirim sadece bir arayüz ve onlar " yöntemleri imza sütunları " muzdarip olmaz , derleyici yaparsanız size bir uyarı atar ve sadece düzeltmek için yöntem imza değiştirmek zorunda kalacak (imza = yöntem adı + params + dönüş tipi) .

public interface Flyer{

    public void makeFly(); // <- method without implementation

}

public class Bird extends Abc implements Flyer{

    public void doAnotherThing(){

    }

    @Override
    public void makeFly(){ // <- implementation of Flyer interface

    }

    // Flyer does not have toString() method or any method from class Object, 
    // no method signature collision will happen here

}

1

Çünkü bir arayüz sadece bir sözleşmedir. Ve bir sınıf aslında veri için bir kaptır.


Çoklu kalıtımla ilgili temel zorluk, bir sınıfın, bir üyeyi, kendi geçersiz kılma uygulamasını sağlamadan, farklı uygulayan birden çok yol aracılığıyla devralma olasılığıdır. Arabirim mirası bunu önler çünkü arabirim üyelerinin uygulanabileceği tek yer, torunları tek mirasla sınırlı olacak sınıflardadır.
Supercat

1

Örneğin, m1 () yöntemine sahip iki A, B sınıfı. Ve C sınıfı hem A, B'yi uzatır.

 class C extends A, B // for explaining purpose.

Şimdi, C sınıfı m1 tanımını arayacaktır. İlk olarak, bulamazsa sınıfta arayacak ve daha sonra ebeveyn sınıfına bakacaktır. Hem A, B tanımına sahiptir Yani burada tanımın seçilmesi gereken belirsizlik oluşur. Bu yüzden JAVA ÇOKLU MİRASI DESTEKLEMEZ.


java derleyicisini derleme yapmaya ne dersiniz, her iki ebeveyn sınıfında da aynı yöntemleri veya değişkenleri tanımlayabiliriz, böylece kodu değiştirebiliriz ...
siluveru kiran kumar

1

Java, iki nedenden ötürü birden fazla kalıtım özelliğini desteklemez:

  1. Java'da her sınıf bir çocuktur Object . Birden fazla süper sınıftan miras alındığında, alt sınıf Object sınıfının özelliğini edinme belirsizliğini kazanır.
  2. Java'da her sınıfın bir yapıcısı vardır, eğer açıkça yazarsak veya hiç yazmazsak. İlk ifade super()supper class yapıcısını çağırmaya çağırıyor. Sınıfın birden fazla süper sınıfı varsa, kafası karışır.

Yani bir sınıf birden fazla süper sınıftan uzandığında derleme zamanı hatası alırız.


0

Örneğin, Sınıf A'nın bir getSomething yöntemine ve Sınıf B'nin bir getSomething yöntemine sahip olduğu ve sınıf C'nin A ve B'yi genişlettiği durumu ele alalım. Hangi yöntemi arayacağınızı belirlemenin bir yolu yoktur.

Arayüzler temel olarak sadece bir uygulayıcı sınıfın hangi yöntemleri içermesi gerektiğini belirtir. Birden fazla arabirim uygulayan bir sınıf, sınıfın tüm bu arabirimlerdeki yöntemleri uygulaması gerektiği anlamına gelir. Whci, yukarıda açıklanan herhangi bir soruna yol açmaz.


2
" Birisi C.getSomething çağırırsa ne olur. " C ++ bir hatadır. Sorun çözüldü.
curiousguy

Mesele buydu ... Bu açık olduğunu düşündüğüm karşı bir örnekti. Bir şey elde etmek için hangi yöntemin çağrıldığını belirlemenin bir yolu olmadığını belirtiyordum. Ayrıca bir yan not olarak, soru c ++ ile değil java ile ilgilidir
John Kane

Ne demek istediğini anlamadığım için üzgünüm. Açıkçası, MI'lı bazı vakalarda belirsizlik vardır. Bu nasıl bir karşı örnek? MI'nın hiçbir zaman belirsizlikle sonuçlanmadığını kim iddia etti? " Ayrıca bir yan not olarak, soru c ++ değil java ile ilgili " Peki?
curiousguy

Sadece bu belirsizliğin neden var olduğunu ve neden arayüzlerle olmadığını göstermeye çalışıyordum.
John Kane

Evet, MI belirsiz çağrılara neden olabilir. Aşırı yükleme de olabilir. Java aşırı yüklemeyi kaldırmalı mı?
curiousguy

0

Test1, Test2 ve Test3'ün üç sınıf olduğu bir senaryo düşünün. Test3 sınıfı, Test2 ve Test1 sınıflarını devralır. Test1 ve Test2 sınıfları aynı yönteme sahipse ve bunu alt sınıf nesnesinden çağırırsanız, Test1 veya Test2 sınıfının yöntemini çağırmak için bir belirsizlik olacaktır, ancak arabirimde herhangi bir uygulama olmadığı için arabirimde böyle bir belirsizlik yoktur.


0

Java, belirsizlik sorunu nedeniyle çoklu kalıtım, çoklu yol ve karma kalıtım desteklemez:

 Scenario for multiple inheritance: Let us take class A , class B , class C. class A has alphabet(); method , class B has also alphabet(); method. Now class C extends A, B and we are creating object to the subclass i.e., class C , so  C ob = new C(); Then if you want call those methods ob.alphabet(); which class method takes ? is class A method or class B method ?  So in the JVM level ambiguity problem occurred. Thus Java does not support multiple inheritance.

çoklu kalıtım

Referans Bağlantısı: https://plus.google.com/u/0/communities/102217496457095083679


0

basit bir şekilde hepimizin bildiği gibi, bir sınıfı devralabilir (genişletebilir), ancak çok fazla arabirim uygulayabiliriz, çünkü arabirimlerde sadece bir işlevsellik söylemiyoruz. java çok sınıf genişletebilir ve bu aynı yöntemlere sahip varsayalım varsayalım .. bu noktada alt sınıf süper sınıf yöntemi çağırmak için çalışırsanız hangi yöntem çalıştırmak için varsayalım ??, derleyici karışık örnek olsun : - birden fazla genişletmeye çalışın ama arayüzler bu yöntemler alt sınıfta uygulamanız gereken organları yok .. birden fazla uygulama için deneyin endişe yok ..


1
Bu örnekleri buraya gönderebilirsiniz. Bu olmadan bu yüzlerce kez 9 yaşındaki soruya metin bloğu gibi görünüyor.
Pochmurnik

-1

* Bu, Java'da yeni başlayan biri olduğum için basit bir cevaptır *

Üç sınıf vardır düşünün X, Yve Z.

Bu yüzden X extends Y, Z Ve her ikisi gibi miras alıyoruz Yve aynı dönüş türüne ve argümanlarına Zsahip bir yöntem alphabet()var. Bu yöntem alphabet()de Ydiyor ilk alfabe görüntülemek ve yöntem alfabe Zdiyor ekran son alfabesi . İşte alphabet()çağrıldığında belirsizlik geliyor X. İlk veya son alfabeyi görüntüleyip görüntülemeyeceği ??? Dolayısıyla java birden fazla mirası desteklemiyor. Arayüzler söz konusu olduğunda, Yve Zarayüz olarak düşünün . Yani her ikisi de yöntem bildirimini içerecek, alphabet()ancak tanımı içermeyecektir . İlk alfabeyi mi, son alfabeyi mi yoksa herhangi bir şey mi görüntüleyeceğini söylemez, sadece bir yöntem beyan ederalphabet(). Yani belirsizliği yükseltmek için bir sebep yok. Yöntemi sınıf içinde istediğimiz her şeyle tanımlayabiliriz X.

Yani bir kelimeyle, Arayüzlerde tanım uygulamadan sonra yapılır, bu yüzden karışıklık olmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.