Zum Inhalt springen
View in the app

A better way to browse. Learn more.

Fachinformatiker.de

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

ArrayList zugriff und Generalisierung/Spezialisierung

Empfohlene Antworten

Veröffentlicht

Hallo an alle,

Ich habe ein Verständnis-Problem:

folgende Vererbungshierarchie ist gegeben:


class A {

  private int a;


  public A(int a) {

    setA(a);

  }


 void doSomething(){

 System.out.println("do Something - class B");

 }


}


class B extends A {


  public B(int a) {

    super(a);

  }


 void doSomething(){

 System.out.println("do Something - class B");

 }


} 

Nun lege ich eine Arraylist an:

ArrayList<A> foo = new ArrayList<A>;

foo.add(new A(1));

foo.add(new B(2));

Und nun möchte ich aus der ArrayList auslesen:


public A getMe(int num){

 return (A) (foo.get(num));

}

Mein Problem das ich damit habe, ist dass die Vererbungshierarchie mir hier irgendwie verloren geht. Wenn ich jetzt die getMe Methode verwende, dann kann ich immer nur das doSomething() von Klasse A aufrufen, nicht aber das von Klasse B auch wenn das Objekt von der Klasse B ist...

Meine Frage ist nun, wie löst man das elegant?

Gibt es einen Weg, um eine Funktion zu schreiben, die mir je nach dem von welcher Klasse das Objekt ist, den richtigen Typ zurückgibt? Prinzipiell kann ja in Java der Rückgabewert einer Funktion nur von einem Typ sein, oder?

also wenn z.B das Element in der ArrayList vom Typ (B) dann gibt er mit ein Objekt vom Typ B zurück und nicht von der Superklasse A...

Ich hoffe ich habe das einigermaßen verständlich erklärt...

Vielen Dank für eure Hilfe im Voraus

Hallo,

alsooo gleich mal ran ans Werk ;-).

1. Warums steht in deiner doSomething-Methode von Klasse A "do Something - class B" ? Müsste da nicht eigentlich "do Something - class A" stehen, damit du unterscheiden kannst, wessen doSomething du gerade aufrufst ?

2. Wenn du ein Objekt der Klasse B hast und in Klasse B die doSomething-Methode der Klasse A überlädst (overload), dann würde ObjektB.doSomething() auf die von Klasse B überladene Funktion (bzw. deren Implementierung) zurückgreifen und nicht auf die von Klasse A.

Soweit zur Vorbereitung - nun zu deiner Frage:

Eine Möglichkeit wäre, dass du einen cast machst. Möglichkeit zwei müsste in etwa so gehen:


package forum;


import java.util.ArrayList;

import java.util.LinkedList;

import java.util.List;


public class ClassHierarchy {



	public static void main(String[] args) {

		ArrayList<List> list = new ArrayList<List>();

		list.add(new LinkedList());

		list.add(new ArrayList<String>());


		System.out.println(list.get(0).getClass());

		System.out.println(list.get(1).getClass());

	}


}

Die erste Ausgabe würde angeben, dass es sich um eine LinkedList handelt während die zweite Ausgabe ein ArrayList angeben würde - alles klar :) ?


public A getMe(int num){

 return (A) (foo.get(num));

}

Mein Problem das ich damit habe, ist dass die Vererbungshierarchie mir hier irgendwie verloren geht. Wenn ich jetzt die getMe Methode verwende, dann kann ich immer nur das doSomething() von Klasse A aufrufen, nicht aber das von Klasse B auch wenn das Objekt von der Klasse B ist...

Rein theoretisch(!) sollte das aber funktionieren. Da ich allerdings auch weiß, daß Du das wohl nicht posten würdest, wenn Du es nicht geprüft hättest, würde ich sagen: Laß' doch mal den Cast da weg. Du hast doch eine List, die Du mit Generics schon "typisiert" hast. Da ist der Cast doch unnötig. Vll. hilft das ...

Rein theoretisch(!) sollte das aber funktionieren. Da ich allerdings auch weiß, daß Du das wohl nicht posten würdest, wenn Du es nicht geprüft hättest, würde ich sagen: Laß' doch mal den Cast da weg. Du hast doch eine List, die Du mit Generics schon "typisiert" hast. Da ist der Cast doch unnötig. Vll. hilft das ...

Mhhh also wenn er auf A casted braucht er sich auch nicht wundern, wenn die Methode von Objekt A aufgerufen wird :P.

Mhhh also wenn er auf A casted braucht er sich auch nicht wundern, wenn die Methode von Objekt A aufgerufen wird :P.

Objekte werden in Java nicht gecasted. Eigentlich werden nur die Referenzen gecasted. Daher wundert er sich zu recht ...

Aber: Ich hab's jetzt selbst getestet:

public class A {

	private int a;


	public A(int a) {

		setA(a);

	}


	public void setA(int a) {

		this.a = a;

	}


	void doSomething(){

		System.out.println("do Something - class A: " + a);

	}

}
public class B extends A {

	public B(int a) {

		super(a);

	}


	void doSomething(){

		System.out.println("do Something - class B");

	}

}
import java.util.ArrayList;



public class Test {

	ArrayList<A> bar = new ArrayList<A>();


	public Test() {

		bar.add(new A(3));

		bar.add(new B(4));

	}


	public A getCasted(int num){

		return (A) (bar.get(num));

	}


	public A getUncasted(int num){

		return bar.get(num);

	}


	public static void main(String args[]) {

		ArrayList<A> foo = new ArrayList<A>();

		foo.add(new A(1));

		foo.add(new B(2));


		System.out.println("For each");

		for(A a : foo) {

			a.doSomething();

		}


		System.out.println("direkter Zugriff");

		foo.get(0).doSomething();

		foo.get(1).doSomething();


		System.out.println("gecasteter Zugriff");

		((A) foo.get(0)).doSomething();

		((A) foo.get(1)).doSomething();


		Test test = new Test();


		System.out.println("direkter Zugriff über Methode");

		test.getUncasted(0).doSomething();

		test.getUncasted(1).doSomething();


		System.out.println("direkter Zugriff über castende Methode");

		test.getCasted(0).doSomething();

		test.getCasted(1).doSomething();


		System.out.println("A-Objekt aus nicht castender Methode");

		A a1 = test.getUncasted(0);

		a1.doSomething();

		A a2 = test.getUncasted(1);

		a2.doSomething();


		System.out.println("A-Objekt aus castender Methode");

		a1 = test.getCasted(0);

		a1.doSomething();

		a2 = test.getCasted(1);

		a2.doSomething();

	}

}

Und folgende Ausgabe bekomme ich:

For each

do Something - class A: 1

do Something - class B

direkter Zugriff

do Something - class A: 1

do Something - class B

gecasteter Zugriff

do Something - class A: 1

do Something - class B

direkter Zugriff über Methode

do Something - class A: 3

do Something - class B

direkter Zugriff über castende Methode

do Something - class A: 3

do Something - class B

A-Objekt aus nicht castender Methode

do Something - class A: 3

do Something - class B

A-Objekt aus castender Methode

do Something - class A: 3

do Something - class B

Also bei mir läuft alles wie erwartet. Vielleicht postet Du einfach mal Deinen echten Quellcode bzw. vielleicht fällt Dir ein Schritt auf, den Du vergessen hast zu erwähnen?

Also bei mir läuft alles wie erwartet. Vielleicht postet Du einfach mal Deinen echten Quellcode bzw. vielleicht fällt Dir ein Schritt auf, den Du vergessen hast zu erwähnen?

Ich denke es liegt an dem, was ich bereits anfangs erwähnt habe: Er hat bei seinen beiden doSomething Methoden "do Something - class B" reingeschrieben - deshalb sieht er natürlich immer nur "do Something - class B" egal ob die Methode von A oder B aufgerufen wird ....

Ich denke es liegt an dem, was ich bereits anfangs erwähnt habe: Er hat bei seinen beiden doSomething Methoden "do Something - class B" reingeschrieben - deshalb sieht er natürlich immer nur "do Something - class B" egal ob die Methode von A oder B aufgerufen wird ....

Wäre natürlich 'ne Erklärung :D

Stimmt schon, Objekte werden nicht gecastet.

Und aufgerufen wird die Methode in in der Hierarchie ganz unten steht. Wenn ein super()-Aufruf erfolgt geht's in der Hierarchie eins hoch, u.s.w.

Archiv

Dieses Thema wurde archiviert und kann nicht mehr beantwortet werden.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.