Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Habe eine Frage zur Vererbung von Interfaces, nehmen wir an ich habe eine Klasse die ein Interface implementiert mit einer Methode x und diese Klasse hat mehrere Methoden wie foo bar etc.
Sagen wir ich habe eine high modul Klassen die dieses Interface instanzieren.
Meine Frage ist kann diese high modul klasse nur auf diese eine Methode x zugreifen von dem Objekt welches das interface implementiert oder kann er auch auf foo und bar zugreifen.
Ich würde ausprobieren aber sitze in der Uni und kein Laptop.
Also ich glaube der kann nur auf x zugreifen aber.
Also was verstehst Du unter "auf die Methode zugreifen"? Das ist nicht ganz deutlich.
Generell: Da die Instanz diese Methoden hat, kannst Du diese auch aufrufen. Diese Aufrufe kannst Du in Java aber nicht direkt machen, da Java ja erst einmal nur weiß, dass die Variable vom Typ des Interfaces ist. Daher musst Du entweder:
- Die Instanz zu dem eigentlichen Typ casten und dann kannst Du die Methoden aufrufen.
- Reflection nutzen um die Methoden zu bekommen und um diese dann aufzurufen.
Also was verstehst Du unter "auf die Methode zugreifen"? Das ist nicht ganz deutlich.
Generell: Da die Instanz diese Methoden hat, kannst Du diese auch aufrufen. Diese Aufrufe kannst Du in Java aber nicht direkt machen, da Java ja erst einmal nur weiß, dass die Variable vom Typ des Interfaces ist. Daher musst Du entweder:
- Die Instanz zu dem eigentlichen Typ casten und dann kannst Du die Methoden aufrufen.
- Reflection nutzen um die Methoden zu bekommen und um diese dann aufzurufen.
Habe eine Frage zur Vererbung von Interfaces, nehmen wir an ich habe eine Klasse die ein Interface implementiert mit einer Methode x und diese Klasse hat mehrere Methoden wie foo bar etc.
Sagen wir ich habe eine high modul Klassen die dieses Interface instanzieren.
Meine Frage ist kann diese high modul klasse nur auf diese eine Methode x zugreifen von dem Objekt welches das interface implementiert oder kann er auch auf foo und bar zugreifen.
Ich würde ausprobieren aber sitze in der Uni und kein Laptop.
Also ich glaube der kann nur auf x zugreifen aber.
Ich würde mal bitten, die Fragen nachvollziehbar zu stellen. Bis jetzt weiß ich immer noch nicht, was du willst. Nutze den CODE-Tag, und schreibe Pseudocode, dann kann man nachvollziehen, was du genau wissen willst.
Gegeben sein ein "Interface inter{/*...*/}", und eine Klasse "class imp implements inter{/* ...*/}" usw.
Also eigentlich solltest Du doch inzwischen ein gewisses Basiswissen zu Java haben. Aber Dir scheinen ja die wichtigsten Grundlagen zu fehlen!
Java:
SomeType variableName;
Dies deklariert eine Variable "variableName" vom Typ SomeType.
Wir gehen jetzt davon aus, dass SomeType ein Interface oder eine Klasse ist!
Nun kann man diese Variable nutzen.
Zuweisung: Man kann dieser Variablen nur Instanzen zugewiesen werden von einer Klasse, die entweder SomeType ist, SomeType implementiert (SomeType ist ein Interface) oder von SomeType erbt (SomeType ist eine Klasse). Umgangssprachlich sagt man dann, dass die Instanz ein SomeType ist. (Ausnahme: null kann auch zugewiesen werden!)
Zugriff auf Elemente von SomeType: Da nur Instanzen zugewiesen werden können, die SomeType sind, kann man in Java nun alle Elemente (Methoden, Felder, ...) direkt nutzen, so die Sichtbarkeit entsprechend gegeben ist.
Also ein kleiner Test:
Java:
import java.io.*;
public class Test {
public interface A {
void a();
}
public class AImpl1 implements A {
public void a() { System.out.println("AImpl1"); }
}
public class AImpl2 implements A {
public void a() { System.out.println("AImpl2"); }
}
public void test() {
A test; // Eine Variable vom Typ A.
test = new AImpl1(); // Wir weisen eine neue Instanz von AImpl1 zu.
test.a(); // AImpl1 wird natürlich ausgegeben.
System.out.println(test.getClass().getName()); // Test$AImpl1
test = new AImpl2(); // Wir weisen eine neue Instanz von AImpl2 zu.
test.a(); // AImpl2 wird natürlich ausgegeben.
System.out.println(test.getClass().getName()); // Test$AImpl2
test = new A() {
public void a() { System.out.println("Ohne Name"); }
};
test.a(); // Ohne Name
System.out.println(test.getClass().getName()); // Test$1 weil 1. annonyme Klasse in Test
}
public static void main (String[] args) {
new Test().test();
}
}
Also hier sieht man: Auch wenn ich die neue Instanz von AImpl1 in die Variable vom Typ A stecke: Es ist immer noch eine AImpl1 Instanz!
Oder mal ganz einfach visuell für Dumme:
Du hast eine Tüte, da kannst Du nur Obst rein tun.
Und nun tust Du da einen Apfel rein. Apfel ist ja Obst.
Was hast Du jetzt in der Tüte? Doch immer noch einen Apfel. Und natürlich kannst Du den nun auch schälen. Obst selbst bietet das nicht an, den gewisse Obstsorten werden nun einmal nicht geschält. Das ist der Fall mit dem Cast:
Du packst also "Obst" aus der Tüte aus.
-> Ist es ist ein Apfel? Ja! Toll, nun behandel ich es wie ein Apfel und schäle den Apfel.
Reflection wäre etwas anderes:
-> Ich hole das Objekt aus der Tüte. Mir ist absolut egal, was es ist aber ich prüfe, ob es dieses Objekt "Schälen" anbietet. Wenn ja, dann wird das Objekt einfach geschält.
Klar, in der Tüte kann kein gekochtes Ei sein, aber dieser Reflection Code würde auch bei einem gekochten Ei funktionieren, einfach nur, weil es geschält werden kann.
Edit: Noch den Fall der Annonymen Klasse hinzugefügt!
Das kommt darauf an, wie du das Objekt hälst. Beispiel:
Java:
public Interface Schwimmfähig {
public void schwimmen();
}
public class Panzer implements Schwimmfähig{
public void fahren(){
}
public void schießen(){
}
@Override
public void schwimmen(){
}
}
public class Ente implements Schwimmfähig{
public void quaken(){
}
@Override
public void schwimmen(){
}
}
public void schwimmÜberDenTeich(Schwimmfähig schwimmer){
schwimmer.schwimmen(); //Ist das jetzt ein Panzer? Oder eine Ente? Oder was anderes?
}
public static int main(String[] args){
//Das geht:
Panzer schwimmfähigerPanzer = new Panzer();
Panzer.schwimmen();
Panzer.schießen();
//Das geht auch:
Ente entchen = new Ente();
entchen.schwimmen();
entchen.quaken();
//Schaue dir jetzt die Methodenaufrufe an:
schwimmÜberDenTeich(schwimmfähigerPanzer);
schwimmÜberDenTeich(entchen);
}
Es kann dir - dem Interface sei Dank - völlig egal sein mit was du die Methode schwimmÜberDenTeich() fütterst. Du weißt, daß du bei einem Objekt, daß das Interface implementiert hat, einen bestimmten Satz an Methoden erwarten kannst und damit irgendwas tun kannst. Stell dir vor, es soll irgendwann mal eine Klasse 'Schiff' erstellt werden, von der du heute noch gar nichts weißt. Aber das Schiff soll über den Teich schwimmen, mit deiner Methode schwimmÜberDenTeich().
Da du über den Rest des Objekts ja nichts wissen mußt - außer daß es die Methode schwimmen() implementiert hat - kann dir das ganz entspannt egal sein.
Das kommt darauf an, wie du das Objekt hälst. Beispiel:
Java:
public Interface Schwimmfähig {
public void schwimmen();
}
public class Panzer implements Schwimmfähig{
public void fahren(){
}
public void schießen(){
}
@Override
public void schwimmen(){
}
}
public class Ente implements Schwimmfähig{
public void quaken(){
}
@Override
public void schwimmen(){
}
}
public void schwimmÜberDenTeich(Schwimmfähig schwimmer){
schwimmer.schwimmen(); //Ist das jetzt ein Panzer? Oder eine Ente? Oder was anderes?
}
public static int main(String[] args){
//Das geht:
Panzer schwimmfähigerPanzer = new Panzer();
Panzer.schwimmen();
Panzer.schießen();
//Das geht auch:
Ente entchen = new Ente();
entchen.schwimmen();
entchen.quaken();
//Schaue dir jetzt die Methodenaufrufe an:
schwimmÜberDenTeich(schwimmfähigerPanzer);
schwimmÜberDenTeich(entchen);
}
Es kann dir - dem Interface sei Dank - völlig egal sein mit was du die Methode schwimmÜberDenTeich() fütterst. Du weißt, daß du bei einem Objekt, daß das Interface implementiert hat, einen bestimmten Satz an Methoden erwarten kannst und damit irgendwas tun kannst. Stell dir vor, es soll irgendwann mal eine Klasse 'Schiff' erstellt werden, von der du heute noch gar nichts weißt. Aber das Schiff soll über den Teich schwimmen, mit deiner Methode schwimmÜberDenTeich().
Da du über den Rest des Objekts ja nichts wissen mußt - außer daß es die Methode schwimmen() implementiert hat - kann dir das ganz entspannt egal sein.
Das kommt darauf an, wie du das Objekt hälst. Beispiel:
Java:
public Interface Schwimmfähig {
public void schwimmen();
}
public class Panzer implements Schwimmfähig{
public void fahren(){
}
public void schießen(){
}
@Override
public void schwimmen(){
}
}
public class Ente implements Schwimmfähig{
public void quaken(){
}
@Override
public void schwimmen(){
}
}
public void schwimmÜberDenTeich(Schwimmfähig schwimmer){
schwimmer.schwimmen(); //Ist das jetzt ein Panzer? Oder eine Ente? Oder was anderes?
}
public static int main(String[] args){
//Das geht:
Panzer schwimmfähigerPanzer = new Panzer();
Panzer.schwimmen();
Panzer.schießen();
//Das geht auch:
Ente entchen = new Ente();
entchen.schwimmen();
entchen.quaken();
//Schaue dir jetzt die Methodenaufrufe an:
schwimmÜberDenTeich(schwimmfähigerPanzer);
schwimmÜberDenTeich(entchen);
}
Es kann dir - dem Interface sei Dank - völlig egal sein mit was du die Methode schwimmÜberDenTeich() fütterst. Du weißt, daß du bei einem Objekt, daß das Interface implementiert hat, einen bestimmten Satz an Methoden erwarten kannst und damit irgendwas tun kannst. Stell dir vor, es soll irgendwann mal eine Klasse 'Schiff' erstellt werden, von der du heute noch gar nichts weißt. Aber das Schiff soll über den Teich schwimmen, mit deiner Methode schwimmÜberDenTeich().
Da du über den Rest des Objekts ja nichts wissen mußt - außer daß es die Methode schwimmen() implementiert hat - kann dir das ganz entspannt egal sein.
Zur Übersetzungszeit steht der Typ von Objekten bzw. Variablen fest (= kann man unmittelbar aus dem Code ableiten). Du kannst nur die Methoden verwenden, die der Typ (inkl. seiner Supertypen) deklariert hat.
Das solltest Du eigentlich den Kommentaren und Beispielen von @kneitzel und @White_Fox entnehmen können.
Der new Operator erzeugt ein neues Objekt vom angegebenen Typ und gibt eine Referenz darauf zurück. Man kann also die Methoden dieses Typs verwenden (ich knüpfe mal an das Beispiel von @White_Fox an):
Java:
new Panzer().schießen();
new Panzer() liefert also eine Referenz auf eine Instanz vom Typ Panzer, daher kann die in Typ Panzer deklarierte Methode schießen verwendet werden.
Diese Referenz (=Adresse des Objekts im Hauptspeicher) kann einer Variablen zugewiesen werden, sofern der Typ dieser Variablen zuweisungskompatibel ist. Bei komplexen Datentypen ist das der Fall, wenn es sich um den gleichen Typ oder einer seiner Supertypen handelt.
Java:
Panzer p = new Panzer(); // Variable p vom Typ Panzer speichert Referenz auf Instanz vom Typ Panzer
Schwimmfähig f = new Panzer(); // Variable f vom Typ Schwimmfähig speichert Referenz auf Instanz vom Typ Panzer
Soll nun eine Methode über eine dieser Variablen aufgerufen werden, ist der Typ der Variablen ausschlaggebend. So hat p den Typ Panzer, man kann also über p alle Methoden von Panzer (oder einer seiner Supertypen) aufgerufen werden. Variable f hat dagegen den Typ Schwimmfähig, es können also nur die Methoden von Schwimmfähig (oder einer ihrere Supertypen) aufgerufen werden.
Zur Übersetzungszeit steht der Typ von Objekten bzw. Variablen fest (= kann man unmittelbar aus dem Code ableiten). Du kannst nur die Methoden verwenden, die der Typ (inkl. seiner Supertypen) deklariert hat.
Das solltest Du eigentlich den Kommentaren und Beispielen von @kneitzel und @White_Fox entnehmen können.
Der new Operator erzeugt ein neues Objekt vom angegebenen Typ und gibt eine Referenz darauf zurück. Man kann also die Methoden dieses Typs verwenden (ich knüpfe mal an das Beispiel von @White_Fox an):
Java:
new Panzer().schießen();
new Panzer() liefert also eine Referenz auf eine Instanz vom Typ Panzer, daher kann die in Typ Panzer deklarierte Methode schießen verwendet werden.
Diese Referenz (=Adresse des Objekts im Hauptspeicher) kann einer Variablen zugewiesen werden, sofern der Typ dieser Variablen zuweisungskompatibel ist. Bei komplexen Datentypen ist das der Fall, wenn es sich um den gleichen Typ oder einer seiner Supertypen handelt.
Java:
Panzer p = new Panzer(); // Variable p vom Typ Panzer speichert Referenz auf Instanz vom Typ Panzer
Schwimmfähig f = new Panzer(); // Variable f vom Typ Schwimmfähig speichert Referenz auf Instanz vom Typ Panzer
Soll nun eine Methode über eine dieser Variablen aufgerufen werden, ist der Typ der Variablen ausschlaggebend. So hat p den Typ Panzer, man kann also über p alle Methoden von Panzer (oder einer seiner Supertypen) aufgerufen werden. Variable f hat dagegen den Typ Schwimmfähig, es können also nur die Methoden von Schwimmfähig (oder einer ihrere Supertypen) aufgerufen werden.
Wobei mir bei @mrBrown halt die Abgrenzung fehlt. Auch wenn der Panzer in einer Variable vom Typ Swimable gespeichert ist, kann man alle Methoden von Panzer aufrufen. Nur eben nicht durch direkte Java Aufrufe auf der Variable sondern eben über den Umweg eines Cast oder eben durch Reflection.
Es ist zwar sehr wahrscheinlich, dass Heyoka diese Abgrenzung für sich eh schon gesehen hat, aber diese Abgrenzung selbst ist, so wie ich das sehe, nie gemacht worden.
Du weisst, doch, wenn ich @mrBrown sage, dann meine ich @mihe7 und umgekehrt
Spass beiseite - das trifft euch beide. Deine lange Antwort ebenso wie die die Antwort von @mrBrown.
@mrBrown hatte ja pauschal mit "Ja" geantwortet in #6 und Heyoka fand seine Antwort ja auch ganz toll so wie ich ihn verstanden habe. Kurz, knapp. Bei anderen Antworten muss er zu viel lesen ... da könnte er ja dann auch genau so gut das Script von der Vorlesung lesen... Also hätte uns beiden doch klar sein müssen, dass unsere Antworten so nicht erwünscht sein können von Seiten des TE!
Aber ich meine, bei Deiner Antwort hast Du diese Aspekte von mir auch nicht betrachtet, oder? Muss aber gestehen, dass ich das nicht im Detail gelesen habe, da der Beitrag kam, als ich:
a) zeitlich etwas ausgelasteter war
b) die Motivation gering war, da Heyoka das offensichtlich zu viel Text war und ich mich da eigentlich weniger in diesem Thread aufhalten wollte...
Aber wo man dann wieder etwas mehr Off Topic geworden ist, wollte ich mich doch direkt wieder beteiligen, denn ich will mir von euch nicht vorwerfen lassen, dass nur wegen meinem Desinteresse keine 500 Posts in diesem Thread zustande kommen ....
Nein, ich hab ganz unabhängig versucht (er hat sich stets bemüht...), eine möglichst allgemein gültige und dennoch halbwegs präzise Antwort zu geben. Da bemüht man sich einmal, einen vernünftigen Satz rauszulassen und dann so was (warum gibt es hier keinen *heul*-Smiley?)
"Zur Übersetzungszeit steht der Typ von Objekten bzw. Variablen fest (= kann man unmittelbar aus dem Code ableiten). Du kannst nur die Methoden verwenden, die der Typ (inkl. seiner Supertypen) deklariert hat."
Damit wollte ich mich auf die Übersetzungszeit beschränkt wissen. Reflection geschieht erst zur Laufzeit, im Code werden ja die Methoden von Class, Method, etc. verwendet, und ein Cast dient gerade dazu, dem Compiler den Typ mitzuteilen.