Dlaczego wielokrotne dziedziczenie nie jest dozwolone w Javie lub C#?

Wiem, że wielokrotne dziedziczenie nie jest dozwolone w Javie i C#. Wiele książek po prostu powiedzieć, wielokrotne dziedziczenie nie jest dozwolone. Ale można go zaimplementować za pomocą interfejsów. Nic nie jest dyskutowane o tym, dlaczego nie jest dozwolone. Czy ktoś może mi dokładnie powiedzieć, dlaczego nie jest to dozwolone?

Author: Jon Schneider, 2009-06-15

17 answers

Krótka odpowiedź brzmi: ponieważ projektanci języka zdecydowali się nie.

Zasadniczo wydawało się, że zarówno projektanci.NET, jak i Java nie zezwalają na wielokrotne dziedziczenie, ponieważ uzasadnili, że dodanie MI dodaje zbyt wiele złożoności do języków, zapewniając jednocześnie zbyt małe korzyści.

Aby uzyskać bardziej przyjemną i dogłębną lekturę, w sieci dostępne są artykuły z wywiadami niektórych projektantów języka. Na przykład dla. NET, Chris Brumme (który pracował w MS nad CLR) wyjaśnił powody, dla których zdecydowali się nie:

  1. Różne języki mają różne oczekiwania co do tego, jak MI działa. Na przykład, jak konflikty są rozwiązane i czy duplikaty baz są połączone lub zbędne. Before we can zaimplementować MI w CLR, musimy zrobić przegląd wszystkich języków, rysunek się wspólne koncepcje i decydują jak je wyrazić w sposób neutralny językowo. My również trzeba zdecyduj, czy mi należy do CLS i co to oznacza dla języki, które nie chcą tego pojęcia (przypuszczalnie VB.NET, na przykład). Z oczywiście, tym się zajmujemy jako wspólny język runtime, ale my nie mam czasu na robienie tego dla MI jeszcze.

  2. Liczba miejsc, w których MI jest naprawdę odpowiednia, jest całkiem małe. W wielu przypadkach, wiele dziedziczenie interfejsu może dostać pracę zrobione. W innych przypadkach można być w stanie używać enkapsulacji i delegacja. Gdybyśmy mieli dodać nieco inna konstrukcja, jak mixins, czy faktycznie byłoby to bardziej potężny?

  3. Dziedziczenie wielu implementacji wprowadza wiele złożoności do wdrożenie. Ta złożoność Impact casting, layout, dispatch, dostęp do pola, serializacja, tożsamość porównania, weryfikowalność, refleksji, generyki i prawdopodobnie w wielu innych miejscach.

... czytaj całość artykuł tutaj.

Dla Javy możesz przeczytać ten artykuł :

Przyczyny pominięcia wielu dziedziczenie z języka Java głównie wynika z "prostego, przedmiotu zorientowany i znajomy " cel. Jako simple language, twórcy Javy chciał języka, który większość programistów może uchwycić bez rozległych trening. W tym celu pracowali nad uczynić język tak podobny do C++, jak możliwe (znane) bez przenoszenia NAD C++ ' s niepotrzebna złożoność (proste).

W opinii projektantów, wiele dziedziczenie powoduje więcej problemów i zamieszanie niż rozwiązuje. Więc tną wielokrotne dziedziczenie z języka (tak jak przecinają operator przeciążenia). Rozbudowane przez projektantów Doświadczenie w C++ nauczyło ich, że wielokrotne dziedziczenie po prostu nie było warte ból głowy.

 131
Author: Razzie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-13 20:09:20

Wielokrotne dziedziczenie implementacji jest tym, co nie jest dozwolone.

Problem polega na tym, że kompilator / runtime nie może dowiedzieć się, co zrobić, jeśli masz klasę Cowboy i Artist, zarówno z implementacjami metody draw (), a następnie próbujesz utworzyć nowy typ CowboyArtist. Co się dzieje po wywołaniu metody draw ()? Ktoś leży martwy na ulicy, czy masz piękną akwarelę?

Myślę, że to się nazywa podwójne dziedzictwo diamentów problem.

 83
Author: duffymo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-15 09:52:59

Powód: Java jest bardzo popularna i łatwa w kodowaniu, ze względu na swoją prostotę.

Więc co kiedykolwiek Programiści Javy czują się trudni i skomplikowani do zrozumienia dla programistów, starali się tego uniknąć. Jednym z takich rodzajów własności jest wielokrotne dziedziczenie.

  1. unikali wskazówek
  2. Uniknęli wielokrotnego dziedziczenia.

Problem z dziedziczeniem wielokrotnym: Problem Diamentowy.

Przykład :

  1. Załóżmy, że Klasa A jest zabawą metodą (). Klasa B I Klasa C wywodzi się z klasy A.
  2. i obie klasy B I C nadpisują metodę fun().
  3. teraz Załóżmy, że klasa D dziedziczy zarówno klasę B, jak i C. (tylko założenie)
  4. Utwórz obiekt dla klasy D.
  5. D D = new d ();
  6. i spróbuj uzyskać dostęp do d.fun(); => czy nazywa się fun klasy B() czy fun klasy C()?

Jest to niejednoznaczność istniejąca w problemie diamentowym.

Nie jest niemożliwe, aby rozwiązać ten problem, ale to tworzy więcej zamieszania i złożoności dla programisty podczas jego czytania. Powoduje więcej problemów niż próbuje rozwiązać.

Notatka: ale w dowolny sposób zawsze możesz zaimplementować wiele dziedziczeń pośrednio za pomocą interfejsów.

 19
Author: user1923551,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 07:34:59

Ponieważ Java ma znacznie inną filozofię projektowania niż C++. (Nie będę tu dyskutował o C#.)

W projektowaniu C++, Stroustrup chciał włączyć przydatne funkcje, niezależnie od tego, w jaki sposób można je niewłaściwie wykorzystać. Możliwe jest spieprzenie wielu dziedziczeń, przeciążenia operatorów, szablonów i różnych innych funkcji, ale można również zrobić z nimi bardzo dobre rzeczy.

Filozofia projektowania Javy ma na celu podkreślenie bezpieczeństwa w konstrukcjach językowych. W rezultacie są rzeczy, które są o wiele bardziej niezręczne, ale możesz być o wiele bardziej pewny, że kod, na który patrzysz, oznacza to, co myślisz, że robi.

Ponadto Java była w dużej mierze reakcją C++ i Smalltalk, najbardziej znanych języków OO. Istnieje wiele innych języków oo (Common Lisp był właściwie pierwszym, który został ustandaryzowany), z różnymi systemami oo, które lepiej obsługują MI.

Nie wspominając o tym, że jest to całkowicie możliwe, aby zrobić MI w Java, za pomocą interfejsów, kompozycji i delegacji. Jest bardziej wyrazisty niż w C++ i dlatego jest niezgrabniejszy w użyciu, ale da ci coś, co łatwiej zrozumiesz na pierwszy rzut oka.

Tu nie ma prawidłowej odpowiedzi. Odpowiedzi są różne, a to, które z nich jest lepsze dla danej sytuacji, zależy od aplikacji i indywidualnych preferencji.

 13
Author: David Thornley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-15 18:01:29

Głównym (choć bynajmniej nie jedynym) powodem, dla którego ludzie odchodzą od MI, jest tak zwany "problem diamentów" prowadzący do dwuznaczności w Twojej implementacji. Ten artykuł Wikipedii omawia go i wyjaśnia lepiej niż mogłem. MI może również prowadzić do bardziej skomplikowanego kodu, a wielu projektantów OO twierdzi, że nie potrzebujesz MI, a jeśli go używasz, twój model prawdopodobnie się myli. Nie jestem pewien, czy Zgadzam się z tym ostatnim punktem, ale utrzymanie rzeczy prostych jest zawsze dobrym planem.

 12
Author: Steve Haigh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-27 15:45:35

W C++ dziedziczenie wielokrotne było głównym bólem głowy, gdy było używane nieprawidłowo. Aby uniknąć tych popularnych problemów projektowych, w nowoczesnych językach (java, C#) wymuszono dziedziczenie wielu interfejsów.

 8
Author: inazaruk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-15 09:56:11

Dziedziczenie wielokrotne jest

  • trudno zrozumieć
  • trudne do debugowania (na przykład, jeśli mieszasz klasy z wielu frameworków, które mają identyczne metody w głębi duszy, mogą wystąpić nieoczekiwane synergie)
  • łatwy w użyciu
  • nie do końca to przydatne
  • trudne do zaimplementowania, zwłaszcza jeśli chcesz to zrobić poprawnie i efektywnie

Dlatego można uznać za mądry wybór Nie zawierać Wielokrotne dziedziczenie w języku Java.

 8
Author: mfx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-15 11:14:29

Innym powodem jest to, że dziedziczenie jednostkowe sprawia, że rzucanie jest trywialne, nie emitując żadnych instrukcji asemblera (poza sprawdzaniem zgodności typów tam, gdzie jest to wymagane). Jeśli masz dziedziczenie wielokrotne, musisz dowiedzieć się, gdzie w klasie dzieci zaczyna dany rodzic. Tak więc wydajność jest z pewnością atutem(choć nie jedynym).

 5
Author: Blindy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-15 10:02:47

Przyjmuję stwierdzenie, że "wielokrotne dziedziczenie nie jest dozwolone w Javie" z przymrużeniem oka.

Dziedziczenie wielokrotne jest definiowane, gdy " Typ "dziedziczy z więcej niż jednego "typu". Interfejsy są również klasyfikowane jako typy, ponieważ mają zachowanie. Więc Java ma wiele dziedziczeń. Tylko, że jest bezpieczniej.

 4
Author: Rig Veda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-15 17:27:38

Dynamiczne ładowanie klas utrudnia implementację dziedziczenia wielokrotnego.

W Javie unikali złożoności dziedziczenia wielokrotnego, zamiast tego używali pojedynczego dziedziczenia i interfejsu. Złożoność dziedziczenia wielokrotnego jest bardzo wysoka w sytuacji opisanej poniżej

diamentowy problem dziedziczenia wielokrotnego. Mamy dwie klasy B I C dziedziczące z A. Załóżmy, że B I C są nadrzędne wobec metody dziedziczonej i zapewnij własną realizację. Teraz d dziedziczy zarówno z B jak i C wykonując wiele dziedziczeń. D powinien dziedziczyć tę nadpisaną metodę, jvm nie może zdecydować, która nadpisana metoda zostanie użyta?

W c++ do obsługi służą funkcje wirtualne i musimy to zrobić jawnie.

Można tego uniknąć za pomocą interfejsów, nie ma ciał metod. Interfejsy nie mogą być tworzone instancyjnie-mogą być implementowane tylko przez klasy lub rozszerzane przez inne Interfejsy.

 4
Author: sujith s,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-12 11:44:43

W dawnych czasach (lata 70.), kiedy Informatyka była bardziej nauką i mniej masową produkcją, programiści mieli czas, aby pomyśleć o dobrym projekcie i dobrej implementacji, a w rezultacie produkty ( programy) charakteryzowały się wysoką jakością (np. Projektowanie i implementacja TCP/IP). W dzisiejszych czasach, gdy wszyscy programują, a menedżerowie zmieniają specyfikacje przed terminami, subtelne problemy, takie jak te opisane w linku do wikipedii z postu Steve 'a Haigh' a, są trudne do wyśledzenia; dlatego "dziedziczenie wielokrotne" jest ograniczone przez konstrukcję kompilatora. Jeśli ci się spodoba, nadal możesz używać C++ .... i miej tyle wolności, ile chcesz:)

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-15 10:31:10

W rzeczywistości dziedziczenie wielokrotne powstanie złożoności, jeśli odziedziczone klasy mają tę samą funkcję. ie kompilator będzie miał zamieszanie, które trzeba wybrać(problem diamond). Więc w Javie, że złożoność usunięte i dał interfejs, aby uzyskać funkcjonalność jak wiele dziedziczenia dał. Możemy użyć interfejsu

 3
Author: Jinu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-05 09:59:44

Java ma pojęcie, czyli polimorfizm. Istnieją 2 rodzaje polimorfizmu w Javie. Istnieją metody przeciążające i nadpisujące metody. Wśród nich nadpisywanie metod odbywa się z relacją super - i podklasową. Jeśli tworzymy obiekt podklasy i wywołujemy metodę superclass, a jeśli podklasa rozszerza więcej niż jedną klasę, którą metodę super klasy należy wywołać?

Lub, wywołując konstruktor superclass przez super(), który konstruktor super klasy otrzyma dzwonił?

Ta decyzja jest niemożliwa dzięki obecnym funkcjom java API. więc wielokrotne dziedziczenie nie jest dozwolone w Javie.

 2
Author: Abhay Kokate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 18:04:28

Dziedziczenie wielokrotne nie jest dozwolone bezpośrednio w Javie, ale poprzez interfejsy jest dozwolone.

Powód:

Dziedziczenie wielokrotne: wprowadza większą złożoność i wieloznaczność.

Interfejsy: interfejsy są całkowicie abstrakcyjnymi klasami w Javie, które zapewniają jednolity sposób na właściwe określenie struktury lub wewnętrznego działania programu z jego publicznie dostępnego interfejsu, a konsekwencją jest większa elastyczność i Kod wielokrotnego użytku, a także większą kontrolę nad tym, jak tworzysz i współdziałasz z innymi klasami.

Dokładniej, są to specjalne konstrukcje w Javie z dodatkowymi cechami, które pozwalają na wykonywanie pewnego rodzaju dziedziczenia wielokrotnego, tzn. klas, które mogą być przypisane do więcej niż jednej klasy.

Weźmy prosty przykład.

  1. Załóżmy, że istnieją 2 klasy klasy A i B o tych samych nazwach metod, ale różnych funkcjach. Poprzez następujący kod ze słowem kluczowym (extends) dziedziczenie wielokrotne nie jest możliwe.

       public class A                               
         {
           void display()
             {
               System.out.println("Hello 'A' ");
             }
         }
    
       public class B                               
          {
            void display()
              {
                System.out.println("Hello 'B' ");
              }
          }
    
      public class C extends A, B    // which is not possible in java
        {
          public static void main(String args[])
            {
              C object = new C();
              object.display();  // Here there is confusion,which display() to call, method from A class or B class
            }
        }
    
  2. Ale poprzez interfejsy, ze słowem kluczowym (implementuje) możliwe jest wielokrotne dziedziczenie.

    interface A
        {
           // display()
        }
    
    
     interface B
        {
          //display()
        }
    
     class C implements A,B
        {
           //main()
           C object = new C();
           (A)object.display();     // call A's display
    
           (B)object.display(); //call B's display
        }
    }
    
 1
Author: Chaitra Deshpande,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-06 16:32:35

W C++ Klasa może dziedziczyć (bezpośrednio lub pośrednio) z więcej niż jednej klasy, która jest określana jako dziedziczenie wielokrotne .

C# i Java, jednak ograniczają klasy do pojedynczego dziedziczenia każda klasa dziedziczy z klasy samotnego rodzica.

Dziedziczenie wielokrotne jest użytecznym sposobem tworzenia klas, które łączą aspekty dwóch różnych klas hierarchii, co często zdarza się podczas używania różnych frameworków klas w ramach jednego podanie.

Jeśli dwie frameworki definiują własne klasy bazowe dla WYJĄTKÓW, na przykład, możesz użyj dziedziczenia wielokrotnego, aby utworzyć klasy wyjątków, które mogą być używane w obu frameworkach.

Problem z dziedziczeniem wielokrotnym polega na tym, że może to prowadzić do niejednoznaczności. Klasycznym przykładem jest, gdy klasa dziedziczy z dwóch innych klas, z których każda dziedziczy z tej samej klasy:

class A {
    protected:
    bool flag;
};
class B : public A {};
class C : public A {};
class D : public B, public C {
    public:
    void setFlag( bool nflag ){
        flag = nflag; // ambiguous
    }
};

W tym przykładzie element danych flag jest zdefiniowany przez class A. Ale class D zstępuje od class B i class C, które oba wywodzą się z A, więc w istocie dostępne są dwie kopie z flag, ponieważ dwa instancje {[7] } znajdują się w hierarchii klas D. Który chcesz ustawić? Kompilator będzie narzekał że odniesienie do flag w D jest niejednoznaczne . Jedną z poprawek jest jawne disambiguate reference:

B::flag = nflag;

Kolejną poprawką jest zadeklarowanie B I C jako virtual base classes, co oznacza, że tylko jedna kopia a może istnieć w hierarchii, eliminując wszelkie dwuznaczność.

Istnieją inne złożoności z dziedziczeniem wielokrotnym, takie jak kolejność, w jakiej klasy bazowe są inicjowane, gdy obiekt Pochodny jest konstruowany, lub sposób, w jaki członkowie mogą być przypadkowo Ukryte z klas pochodnych. Aby uniknąć tych zawiłości, niektóre języki ograniczają się do prostszego modelu pojedynczego dziedziczenia.

Chociaż znacznie upraszcza to dziedziczenie, ogranicza również jego przydatność ponieważ tylko klasy ze wspólnym przodkiem mogą współdzielić zachowania. Interfejsy ograniczenie nieco poprzez umożliwienie klasom w różnych hierarchiach ujawniania wspólnych interfejsów nawet jeśli nie są zaimplementowane przez współdzielenie kodu.

 1
Author: robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-19 06:06:34
Czy ktoś może mi dokładnie powiedzieć, dlaczego nie jest to dozwolone?

Możesz znaleźć odpowiedź z tej dokumentacji link

Jednym z powodów, dla których język programowania Java nie pozwala na rozszerzenie więcej niż jednej klasy, jest unikanie problemów z wielokrotnym dziedziczeniem stanu, czyli możliwością dziedziczenia pól z wielu klas

Jeśli dozwolone jest dziedziczenie wielokrotne i kiedy tworzysz obiekt przez utworzenie instancji tej klasy, to obiekt dziedziczy pola ze wszystkich superklas klasy. Spowoduje to dwa problemy.

  1. Co jeśli metody lub konstruktory z różnych super klas tworzą instancję tego samego pola?

  2. Która metoda lub konstruktor będzie miała pierwszeństwo?

Nawet jeśli wielokrotne dziedziczenie stanu jest teraz dozwolone, nadal możesz zaimplementować

Dziedziczenie wielokrotne typu: zdolność klasy do implementacji więcej niż jednego interfejs.

Dziedziczenie wielu implementacji (poprzez domyślne metody w interfejsach): możliwość dziedziczenia definicji metod z wielu klas

Zobacz to powiązane pytanie SE, aby uzyskać dodatkowe informacje:

Wieloznaczność dziedziczenia z interfejsem

 0
Author: Ravindra babu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:23

Wyobraź sobie ten przykład: Mam klasę Shape1

Ma CalcualteArea metodę:

Class Shape1
{

 public void CalculateArea()

     {
       //
     }
}

Istnieje inna klasa Shape2, która również ma tę samą metodę

Class Shape2
{

 public void CalculateArea()

     {

     }
}

Teraz mam dziecięcy krąg klasowy, wywodzi się zarówno z Shape1, jak i Shape2;

public class Circle: Shape1, Shape2
{
}

Teraz, kiedy tworzę obiekt dla Circle i wywołuję metodę, system nie wie, którą metodę Oblicz obszar należy wywołać. Oba mają te same podpisy. Więc kompilator się pomyli. Dlatego wiele spadków nie jest dozwolone.

Ale może być wiele interfejsów, ponieważ interfejsy nie mają definicji metody. Nawet oba interfejsy mają tę samą metodę, oba nie mają żadnej implementacji i zawsze zostanie wykonana metoda w klasie potomnej.

 -3
Author: Engr Muhammad Enayet Abdullah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-28 06:12:44