Problem bei Vererbung abstrakter Klassen

djafix

Mitglied
Hallo Leute,
ich habe ein Problem bei der Umsetzung des Beobachter-Patterns zur Nutzung des MVC-Entwurfsmusters:

Ich habe zuerst eine abstrakte Klasse "AbstractObserver" erstellt. Diese Realisiert die Funktionalitäten des Beobachters. Danach habe ich eine Klasse "AbstractView" erstellt, die diese Klasse spezialisiert. Diese hat zusätzlich als Attribut eine Instanz vom Typ "Model". Model widerum hat als Attribut eine Instanz einer Klasse "Problem" und eine Methode "Problem getProblem()".

Wenn ich jetzt anfang eine Klasse "TextView" zu erstellen (diese spezialisiert AbstractView), und in dieser in der update-Methode (die Methode die beschreibt, wie der Observer/die View mit Änderungen des Observables/Models umgeht) die Methode "this.Observable.getProblem()" aufrufen will, bringt mir der Compiler die Meldung, dass die Klasse AbstractObservable keine Methode namens "getProblem()" enthält.

Aber zu diesem Zeitpunkt ist das "AbstractObservable" ja bereits vom Typ "Model". Deshalb frage ich mich, warum die Methode dort nicht aufgerufen werden kann. Ich habe absolut keine Ahnung, woran das liegen könnte ???:L. Hier ist noch der Quelltext der einzelnen Klassen (das ist jetzt sicherlich extrem viel, aber ich hoffe es findet sich jemand, der mir helfen kann 🙁 )

Java:
package observerPattern;
import problem.*;
public abstract class AbstractObserver implements ObserverInterface {

	protected AbstractObservable observable;
	public abstract void update();

	public void setObservable(AbstractObservable observable){
		//this.observable.deleteObserver(this);
		this.observable = observable;
		this.observable.registerObserver(this);
	}
	
}

Java:
package view;
import observerPattern.*;
import model.*;
public abstract class AbstractView extends AbstractObserver implements ViewInterface {

	String name;
	
	public AbstractView(String name){
		super();
		this.name = name;
		this.setObservable(new Model());

	}
	
	public void setName(String name){
		this.name = name;
	}
	public String getName(){
		return name;
	}
	
	public abstract void resetView();
	
}
Java:
package view;
import problem.*;
import observerPattern.*;
import model.*;
public class TextView extends AbstractView {

	String text = "";

	public TextView(){
		super("TextView");
	}
	public void resetView(){
		this.text = "";
	}
	public void update(){
		//hier wird entschieden, wie TextView mit einer Änderung des Models/Problems umgeht
		Problem tempProblem = observable.getProblem(); // HIER TRITT DER FEHLER AUF!!!!
		System.out.println(tempProblem.getIsFinished());
	}
	
	
}
Java:
package observerPattern;
import java.util.*;
import problem.*;



public abstract class AbstractObservable{

	protected List<AbstractObserver> observers;
	Object object = new Object();

	public AbstractObservable(){
		observers = new ArrayList<AbstractObserver>();
	}
	public void registerObserver(AbstractObserver observer){
		observers.add(observer);
	}
	public void deleteObserver(AbstractObserver observer){
		observers.remove(observer);
	}
	public void notifyObservers(){
		
		for(AbstractObserver o : observers){
			o.update();
		}
		
	}
	public void update(Object newProblem){
		this.object = newProblem;
		notifyObservers();
	}
	public Object getObject(){
		return this.object;
	}

	
	
}
Java:
package model;
import observerPattern.*;
import problem.*;
import algorithm.*;
public abstract class AbstractModel extends AbstractObservable{

	
	AbstractAlgorithm algorithm;
	protected Problem problem;
	public void performAlgorithm(){
		
	}


	public void performStep(){
		this.algorithm.performStep();
	}
	public AbstractModel(){
		super();
		this.problem = new Problem();
		this.algorithm = new ForwardScheduling(this.problem);
		
	}
	public Problem getProblem(){
		return this.problem;
	}
	
}
Java:
package model;

public class Model extends AbstractModel{

}
Schonmal danke im Vorraus an alle 🙂
 
Zuletzt bearbeitet:
Hallo

Java:
Problem tempProblem = observable.getProblem();
Also: die Variable observable ist eine Instanz der Klasse AbstractObservable. Kannst du darin eine Methode getProblem() finden? Nein! Du musst also, versuchen observable erst in ein AbstractModel zu casten:
Java:
((AbstractModel) obersable).getProblem();

Wollt noch mehr schreiben, muss aber zum Zahnarzt bis gleich 😀
 
Zuletzt bearbeitet:
Da der Compiler meckert, wir es zur Compile-Zeit entschieden. Und da sieht der Compiler nur, dass
Code:
observable
vom Typ
Code:
AbstractObservable
ist. Und dieser hat keine Methode
Code:
getProblem()
.

Du könntest
Code:
AbstractObserver
parametrisieren, sodass du über Gernerics den Typ des verwendenten Observers festlegen kannst:
Java:
public abstract class AbstractObserver<O extends  AbstractObservable> implements ObserverInterface {
 
    protected O observable;
    public abstract void update();
 
    public void setObservable(O observable){
    ...
    }
}

AbstractView könntest du dann so implementieren:

Java:
public abstract class AbstractView extends AbstractObserver<Model> implements ViewInterface {
...
[/Java]
 
Zuletzt bearbeitet:
Was ich noch dazu sagen wollte, in der Java API gibt es bereits die Klasse [JAPI]Observable[/JAPI] und das Interface [JAPI]Observer[/JAPI], welche du nutzen kannst.

Wenn es dir aber um das Pattern geht, sei gesagt, dass sich normalerweise der Observer beim Observable registriert. Was du bisher auch machst, aber die Methode setObservable sieht mir etwas unstimmig aus. Die Observer bekommen vom Observable Informationen und müssen von diesem Observable eigentlich nichts wissen.
 
Zuletzt bearbeitet:
@Natac:das mit den generics werde ich mal ausprobieren. aber ich hatte gedacht, man könnte das auch etwas einfacher lösen indem man z.b. im konstruktor von TextView dem compiler sagt, dass observable nun vom typ model ist
Code:
this.observable = new Model();

@hauptDev: die referenz auf das observable habe ich ja genau deshalb eingeführt, damit ich dann (wenn es dann funktioniert) auf die methoden des observables in der update-methode zugreifen kann. oder ist es im sinne des observer-patterns besser, einfach eine referenz auf das observable in der parameterliste von update mitzugeben? vielleicht würde das auch schon direkt mein problem lösen..das werden ich dann gleich mal ausprobieren :idea:

ob es für meinen zweck sinn macht, das observable und den observer der java API zu nutzen weiß ich nicht genau, da ja dort z.b. die update-methode lediglich ein argument vom typ observable und vom typ object enthält....oder könnte man anstelle von object auch einfach model nutzen? (theoretisch erbt model ja sowieso von object)

edit: so ich habe jetzt beides ausprobiert, einmal die klassen als generics zu implementieren und einmal in der update-methode eine referenz auf
Code:
this
zu übergeben. aus einem mir immernoch unbekannten grund merkt
Code:
TextView
einfach nicht, dass es sich bei der übergebenen referenz um ein
Code:
Model
und nicht um einen
Code:
AbstractObserver
handelt. ich bin da langsam mit meiner vorstellungskraft am ende, warum das so sein könnte
 
Zuletzt bearbeitet:
sooo,ich hab noch bisschen rumprobiert und das problem jetzt gelöst, indem ich observer und observable aus der java-api ableiten lassen hab und dann in der update-methode des observers das "object" zu model gecastet habe.

Java:
	@Override
	public void update(Observable observable, Object model) {
		Model tempModel = (Model)model;
		Problem tempProblem = tempModel.getProblem();
		
		System.out.println(tempProblem.getIsFinished());
		
	}

und das funktioniert auch 😀 allerdings frage ich mich, warum der cast nicht auch mit meinen selbst erstellten observer- und observable-klassen funktioniert hat...

jedenfalls vielen dank für eure hilfe! 🙂
 

Zurück
Oben