Nie możesz jednocześnie przedłużyć dwóch lub więcej zajęć. Dziedziczenie wielokrotne nie jest dozwolone w Javie.
yogsma
Odpowiedzi:
156
Możesz rozszerzyć tylko jedną klasę. I implementuj interfejsy z wielu źródeł.
Przedłużanie wielu klas nie jest dostępne. Jedynym rozwiązaniem, które przychodzi mi do głowy, nie jest dziedziczenie żadnej z klas, ale zamiast tego posiadanie wewnętrznej zmiennej każdej klasy i robienie więcej z proxy, przekierowując żądania do obiektu do obiektu, do którego mają trafiać.
publicclassCustomActivityextendsActivity{privateAnotherClass mClass;protectedvoid onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);
mClass =newAnotherClass(this);}//Implement each method you want to use.publicString getInfoFromOtherClass(){return mClass.getInfoFromOtherClass();}}
to najlepsze rozwiązanie, jakie wymyśliłem. Możesz uzyskać funkcjonalność z obu klas, a nadal może być tylko jednego typu.
Wadą jest to, że nie można dopasować się do klasy formy wewnętrznej za pomocą odlewu.
Ciekawe podejście, co eksperci sądzą o tej technice? Chciałbym się w to zagłębić.
TechNyquist
1
Czy to jest w porządku z konwencjami?
totten
2
Nie można zmusić klasy wewnętrznej do pracy w Fragment. Moja aktywność musi się rozszerzać Fragment, co oznacza, że absolutnie potrzebuję getView(), co nie zadziała, jeśli znajduje się w klasie wewnętrznej, a kod tam jest, z którego muszę użyć kodu ListActivity, więc nie mogę dwukrotnie rozszerzyć LUB zrobić klasy wewnętrznej w tym przykładzie.
Azurespot
Jest to najlepsze rozwiązanie do rozszerzania klas abstrakcyjnych, w których potrzebny jest dostęp do zmiennych klasy implementującej.
tak3shi
45
Jak wszyscy powiedzieli. Nie, nie możesz. Jednak nawet jeśli ludzie wielokrotnie powtarzali przez lata, że powinieneś używać wielu interfejsów, tak naprawdę nie wnikali w to, jak to zrobić. Mam nadzieję, że to pomoże.
Powiedzmy, że masz class Fooi class Baroboje chcecie spróbować rozszerzyć do class FooBar. Oczywiście, jak powiedziałeś, nie możesz:
publicclassFooBarextendsFoo,Bar
Ludzie do pewnego stopnia już wnikali w przyczyny takiego stanu rzeczy. Zamiast tego napisz interfacesdla obu Fooi Baromów wszystkie ich publiczne metody. Na przykład
Teraz, z class FooBar, można realizować zarówno FooInterfacei BarInterfaceprzy zachowaniu Fooi Barobiekt i tylko przejazdem metody prosto przez:
publicclassFooBarimplementsFooInterface,BarInterface{Foo myFoo;Bar myBar;// You can have the FooBar constructor require the arguments for both// the Foo and the Bar constructorspublicFooBar(int x,int y,int z){
myFoo =newFoo(x);
myBar =newBar(y, z);}// Or have the Foo and Bar objects passed right inpublicFooBar(Foo newFoo,Bar newBar){
myFoo = newFoo;
myBar = newBar;}publicvoid methodA(){
myFoo.methodA();}publicint methodB(){return myFoo.methodB();}publicint methodC(int i){return myBar.methodC(i);}//...}
Zaletą tej metody jest to, że FooBarprzedmiot pasuje do formy zarówno FooInterfacei BarInterface. Oznacza to, że wszystko jest w porządku:
To bardzo dobra odpowiedź, ale widzę kilka problemów, które wymagają bardziej szczegółowego rozwiązania. Po pierwsze rozszerzenie z dwóch istniejących klas byłoby nieco bardziej problematyczne i wymagałoby przejścia przez szereg dodatkowych przeszkód. Po drugie, gdyby interfejs Foo i Bar miały te same funkcje, musiałbyś mieć kolejność pierwszeństwa. Wyraźne rozszerzenie klasy zmusiłoby cię do podjęcia tych decyzji z góry. Mimo to doskonała opcja :) +1
The Lazy Coder
A jeśli będziemy musieli „często” tworzyć nowe klasy i sprawić, by każda z tych klas implementowała oba interfejsy? Następnie musielibyśmy powtórzyć te standardowe implementacje w każdej klasie. Czy istnieje lepszy sposób, aby klasa „zaimplementowała” dwa zestawy zachowań?
MasterJoe2,
1
@ MasterJoe2 Szczerze mówiąc, od jakiegoś czasu nie robiłem zbyt wiele z Javą (zatrzymałem się mniej więcej w czasie, gdy pisałem tę odpowiedź). Jednym z powodów, dla których teraz tego unikam, jest sam problem, który podnosisz. Przeczuciem w kierunku, który mógłbyś ewentualnie zbadać, jest napisanie klasy abstrakcyjnej, która implementuje oba interfejsy i rozszerza to. Nie mam jednak pojęcia, czy to poprawna Java i czuję, że po prostu skończysz z tym samym pierwotnym problemem, gdy będziesz chciał wprowadzić zmiany w klasie implementującej w przyszłości. Przepraszam, nie mogę być bardziej pomocny.
SCB
37
Będziesz chciał używać interfejsów. Generalnie dziedziczenie wielokrotne jest złe z powodu problemu diamentowego:
abstractclass A {abstract string foo();}class B extends A {
string foo (){return"bar";}}class C extends A {
string foo(){return"baz";}}class D extends B, C {
string foo(){returnsuper.foo();}//What do I do? Which method should I call?}
C ++ i inne mają kilka sposobów rozwiązania tego problemu, np
Nigdy nie rozumiałem, dlaczego problem z diamentami jest w rzeczywistości problemem, który zapobiega wielokrotnemu dziedziczeniu. Dlaczego kompilator nie może po prostu narzekać, jeśli istnieją sprzeczne metody o tej samej nazwie?
pete
1
W przypadku wystarczająco inteligentnych kompilatorów tak nie jest. Rozwiązanie tego na poziomie kompilatora jest możliwe i rzeczywiście C ++ robi to z virtual class. Takie postępowanie wiąże się z wieloma ostrzeżeniami i zastrzeżeniami, zarówno dla kompilatora, jak i programisty.
David Souther,
1
A co z tymi samymi domyślnymi metodami w dwóch interfejsach? To kolejny przykład problemu z diamentami, z którym może sobie poradzić Java.
Nie możesz zwrócić "bar"ani "baz"z typem metody void. W każdym razie, dobre wyjaśnienie xD
xdevs23
22
Tak, jak wszyscy pisali, w Javie nie można dziedziczyć wielokrotnego. Jeśli masz dwie klasy, z których chciałbyś użyć kodu, zwykle tworzysz podklasę jedną (powiedzmy class A). W przypadku klasy B, przenosisz ważne metody do interfejsu BInterface(brzydka nazwa, ale masz pomysł), a następnie mówisz Main extends A implements BInterface. Wewnątrz możesz utworzyć instancję obiektu klasy Bi zaimplementować wszystkie metody programu BInterface, wywołując odpowiednie funkcje B.
Zmienia to relację „jest-a” w relację „ma-a”, ponieważ twoje Mainteraz jest A, ale ma B. W zależności od przypadku użycia możesz nawet wprowadzić tę zmianę jawnie, usuwając element BInterfacez Aklasy i zamiast tego udostępnić metodę bezpośredniego dostępu do obiektu B.
Podobnie jak inna alternatywa, być może możesz użyć interfejsu z domyślną implementacją metody. To oczywiście zależy od tego, co chcesz zrobić.
Na przykład możesz utworzyć klasę abstrakcyjną i interfejs:
publicabstractclassFatherClass{abstractvoid methodInherit(){//... do something}}publicinterfaceInterfaceWithDefaultsMethods{defaultvoid anotherMethod(){//... do something//... maybe a method with a callable for call another function.}}
Następnie możesz rozszerzyć i zaimplementować obie klasy i użyć obu metod.
Parallaxori ParallaxControllersą nieznane, więc zakładam, że nie są to klasy SDK. Więc to nie działa dla mnie (i dlatego ta odpowiedź pokazuje błędy). Co to jest ParallaxController? Czy to jest konkretna zależność? Proszę rozwinąć
Zoe
1
Twórcy javy zdecydowali, że problemy wielokrotnego dziedziczenia przeważają nad korzyściami, więc nie uwzględnili dziedziczenia wielokrotnego. Możesz przeczytać o jednym z największych problemów związanych z dziedziczeniem wielokrotnym (problem podwójnego diamentu) tutaj .
Dwie najbardziej podobne koncepcje to implementacja interfejsu i dołączanie obiektów innych klas jako elementów składowych bieżącej klasy. Używanie metod domyślnych w interfejsach jest prawie dokładnie tym samym, co dziedziczenie wielokrotne, jednak używanie interfejsu tylko z metodami domyślnymi jest uważane za złą praktykę.
Odpowiedzi:
Możesz rozszerzyć tylko jedną klasę. I implementuj interfejsy z wielu źródeł.
Przedłużanie wielu klas nie jest dostępne. Jedynym rozwiązaniem, które przychodzi mi do głowy, nie jest dziedziczenie żadnej z klas, ale zamiast tego posiadanie wewnętrznej zmiennej każdej klasy i robienie więcej z proxy, przekierowując żądania do obiektu do obiektu, do którego mają trafiać.
to najlepsze rozwiązanie, jakie wymyśliłem. Możesz uzyskać funkcjonalność z obu klas, a nadal może być tylko jednego typu.
Wadą jest to, że nie można dopasować się do klasy formy wewnętrznej za pomocą odlewu.
źródło
Dlaczego nie użyć klasy wewnętrznej (zagnieżdżanie)
źródło
Fragment
. Moja aktywność musi się rozszerzaćFragment
, co oznacza, że absolutnie potrzebujęgetView()
, co nie zadziała, jeśli znajduje się w klasie wewnętrznej, a kod tam jest, z którego muszę użyć koduListActivity
, więc nie mogę dwukrotnie rozszerzyć LUB zrobić klasy wewnętrznej w tym przykładzie.Jak wszyscy powiedzieli. Nie, nie możesz. Jednak nawet jeśli ludzie wielokrotnie powtarzali przez lata, że powinieneś używać wielu interfejsów, tak naprawdę nie wnikali w to, jak to zrobić. Mam nadzieję, że to pomoże.
Powiedzmy, że masz
class Foo
iclass Bar
oboje chcecie spróbować rozszerzyć doclass FooBar
. Oczywiście, jak powiedziałeś, nie możesz:Ludzie do pewnego stopnia już wnikali w przyczyny takiego stanu rzeczy. Zamiast tego napisz
interfaces
dla obuFoo
iBar
omów wszystkie ich publiczne metody. Na przykładA teraz stwórz
Foo
iBar
zaimplementuj odpowiednie interfejsy:Teraz, z
class FooBar
, można realizować zarównoFooInterface
iBarInterface
przy zachowaniuFoo
iBar
obiekt i tylko przejazdem metody prosto przez:Zaletą tej metody jest to, że
FooBar
przedmiot pasuje do formy zarównoFooInterface
iBarInterface
. Oznacza to, że wszystko jest w porządku:Mam nadzieję, że to wyjaśnia, jak używać interfejsów zamiast wielu rozszerzeń. Nawet jeśli spóźnię się kilka lat.
źródło
Będziesz chciał używać interfejsów. Generalnie dziedziczenie wielokrotne jest złe z powodu problemu diamentowego:
C ++ i inne mają kilka sposobów rozwiązania tego problemu, np
ale Java używa tylko interfejsów.
Ścieżki Java mają świetne wprowadzenie do interfejsów: http://download.oracle.com/javase/tutorial/java/concepts/interface.html Prawdopodobnie zechcesz to prześledzić, zanim zagłębisz się w niuanse w Android API.
źródło
virtual class
. Takie postępowanie wiąże się z wieloma ostrzeżeniami i zastrzeżeniami, zarówno dla kompilatora, jak i programisty.super
from w dziedziczeniu metody. Cóż, możesz, ale musisz określić metodę interfejsu do wywołania (i musi ona użyć słowa kluczowegodefault
w implementacji interfejsu) . Przykład:MyIFace.super.foo()
gdzie MyIFace jest interfejsem. Jak widać, metoda interfejsu do wykonania jest zdefiniowana i całkowicie pozwala uniknąć problemu diamentów. Jeśli rozszerzyszMyClass1
iMyClass2
, obie klasy mają afoo()
, i wywołasz,super.foo()
kompilator zostanie zgłoszony przez Diamentowy Problem."bar"
ani"baz"
z typem metodyvoid
. W każdym razie, dobre wyjaśnienie xDTak, jak wszyscy pisali, w Javie nie można dziedziczyć wielokrotnego. Jeśli masz dwie klasy, z których chciałbyś użyć kodu, zwykle tworzysz podklasę jedną (powiedzmy class
A
). W przypadku klasyB
, przenosisz ważne metody do interfejsuBInterface
(brzydka nazwa, ale masz pomysł), a następnie mówiszMain extends A implements BInterface
. Wewnątrz możesz utworzyć instancję obiektu klasyB
i zaimplementować wszystkie metody programuBInterface
, wywołując odpowiednie funkcjeB
.Zmienia to relację „jest-a” w relację „ma-a”, ponieważ twoje
Main
teraz jestA
, ale maB
. W zależności od przypadku użycia możesz nawet wprowadzić tę zmianę jawnie, usuwając elementBInterface
zA
klasy i zamiast tego udostępnić metodę bezpośredniego dostępu do obiektu B.źródło
Stwórz interfejs. Java nie ma wielokrotnego dziedziczenia.
http://csis.pace.edu/~bergin/patterns/multipleinheritance.html
źródło
Java nie obsługuje dziedziczenia wielokrotnego, ale możesz spróbować zaimplementować dwa lub więcej interfejsów.
źródło
Tak. slandau ma rację. Java nie pozwala na rozszerzanie z kilku klas.
Prawdopodobnie chcesz
public class Main extends ListActivity implements ControlMenu
. Domyślam się, że próbujesz zrobić listę.Mam nadzieję, że to pomoże.
źródło
Podobnie jak inna alternatywa, być może możesz użyć interfejsu z domyślną implementacją metody. To oczywiście zależy od tego, co chcesz zrobić.
Na przykład możesz utworzyć klasę abstrakcyjną i interfejs:
Następnie możesz rozszerzyć i zaimplementować obie klasy i użyć obu metod.
Mam nadzieję, że to ci pomoże ...
źródło
Rozszerzanie z wielu klas nie jest dozwolone w Javie, aby zapobiec Deadly Diamond of death !
źródło
to jest możliwe
źródło
Parallaxor
iParallaxController
są nieznane, więc zakładam, że nie są to klasy SDK. Więc to nie działa dla mnie (i dlatego ta odpowiedź pokazuje błędy). Co to jest ParallaxController? Czy to jest konkretna zależność? Proszę rozwinąćTwórcy javy zdecydowali, że problemy wielokrotnego dziedziczenia przeważają nad korzyściami, więc nie uwzględnili dziedziczenia wielokrotnego. Możesz przeczytać o jednym z największych problemów związanych z dziedziczeniem wielokrotnym (problem podwójnego diamentu) tutaj .
Dwie najbardziej podobne koncepcje to implementacja interfejsu i dołączanie obiektów innych klas jako elementów składowych bieżącej klasy. Używanie metod domyślnych w interfejsach jest prawie dokładnie tym samym, co dziedziczenie wielokrotne, jednak używanie interfejsu tylko z metodami domyślnymi jest uważane za złą praktykę.
źródło
nie możesz zrobić wielokrotnego dziedziczenia w java. rozważ użycie interfejsów:
lub klasy wewnętrzne:
źródło