rzutowanie obiektów

0
public class A {
	public void x() {//jakis kod};
}
public class B extends A{
	public void x() {
		//jakis kod
	}

	public void y() {
		//jakis kod
	}
}
A obiekt = new B();
    	obiekt.x();
    	obiekt.y(); // to nie zadziała bo klasa A nie zna metody y();

W takim przypadku przydaje się rzutowanie żeby 'obiekt' otrzymał dostęp do metody y(). Moje pytanie jest takie, czy są jakieś inne przypadki kiedy trzeba rzutować obiekty i czy rzutować można tylko na typy której dany obiekt tą klasę dziedziczy?

0
lofi napisał(a)

Moje pytanie jest takie, czy są jakieś inne przypadki kiedy trzeba rzutować obiekty
W ogóle zamiast rzutować, powinno się wykorzystywać polimorfizm.

lofi napisał(a)

i czy rzutować można tylko na typy której dany obiekt tą klasę dziedziczy?
Jaki byłby sens rzutowania obiektu na klasę, której instancją on być nie może...

0

Zauważ, że pierwsze niejawne rzutowanie masz już kiedy do referencyjnej zmiennej A przypisujesz referencję obiektu B. Ponieważ rzutowanie takie tylko zawęża interfejs, a obiekt potomny wobec rodzica spełnia zawsze relację "jest", to takie rzutowanie masz z automatu. W drugą stronę musisz jawnie sprawdzić relację "is" do czego służy operator instanceof lub metoda isInstance(). Wtedy do dyspozycji jest cała lista typów potomnych, od typu, którego reprezentuje referencja, a aż do typu mającego identyczny plik Class<?>. Czasem bezpieczniej i lepiej wygląda rzutowanie za pomocą metody Class.cast(Object o), której zapis bardziej przypomina rzutowanie w C++.

Innym czasem przydatnym rodzajem rzutowania jest jawne rzutowanie referencji obiektu jakiejś klasy na interfejs (którego ta klasa implementuje), albo bardziej zawężony interfejs któregoś rodzica. Robi się tak po to aby ktoś kto taką referencję dostanie nie próbował wywoływać metod obiektu konkretnego, a jedynie te z interfejsu. Bardzo rzadko bywa też potrzeba rzutowania z jednego interfejsu na inny mając w rzeczywistości obiekt konkretny, który implementuje oba. Jednak takie coś świadczy najczęściej o złym projekcie - szczególnie kiedy oba interfejsy nie mają zależności w pionie (tzn. jako kolejnych rozszerzeń interfejsu).

0

Jeśli spróbujesz rzutować sobie pomiędzy typami które do siebie nie pasują to dostaniesz ClassCastException ;)
Przy czym sam fakt że musisz coś rzutować może (acz nie musi) oznaczać że coś w projekcie jest nie tak.

0

Hmmm, a jeśli o "inne przypadki" chodzi... chyba najklasyczniejszym przypadkiem, gdzie to rzutowanie jest, to by była equals

public class Foo {

    private int p,q;

    public Foo() { /* ... */ }

    @Override
    public int hashCode() {  return /* ... */; }

    @Override
    public boolean equals(Object value) {
        if (value == null) { return false; }

        if (getClass() != value.getClass()) { return false; }

        final Foo foo = (Foo)value;

        if (this.p != foo.p) { return false; }
        if (this.q != foo.q) { return false; }
        return true;
    }

}

Nie kojarzę jakiegoś innego popularnego idiomu, który powszechny jest - coś mi się Swing kojarzy, że tam też by wyszukał różne akcje, gdzie innej rady nie ma.

0

Dobrze Ci się kojarzy. Często źródło zdarzenia otrzymane przez ev.getSource() - jest ono typu Object - jest rzutowane na konkretny komponent.

0

O to to... jak mnie to wkurzało... Nawet się wściekłem i zrobiłem takie cuś (udało się wygrzebać), co po mocnym okrojeniu wyglądałoby tak:

public abstract class QListSelectionListener<Element> implements ListSelectionListener {

    public abstract boolean onSelect(ListSelectionEvent event, int index, Element value);

    public abstract boolean onClear(ListSelectionEvent event);

    public QListSelectionListener(JList list) {
        this.owner = list;
    }

    @Override
    public void valueChanged(ListSelectionEvent event) {
        if( event.getValueIsAdjusting() ) { return; }
        DefaultListSelectionModel selection = (DefaultListSelectionModel)event.getSource();
        int index = selection.getAnchorSelectionIndex();
        if(-1 == index) {
            onClear(event);
        } else {
            onSelect(event, index, (Element)owner.getModel().getElementAt(index) );
        }
    }

    private final JList owner;

}

coby rzutowań i zaznaczenia od zaznaczenia sobie oszczędzić w handlerach... a potem się dowiedziałem, co to jest "unchecked cast" ... i że cały ten kod to można kotu w zad wsadzić. I całe to naklepane dzieło postanowiłem wyprzeć z pamięci. Nie udało się :D Na ile związek z tematem? Głupia obsługa zaznaczenia wiersza - i i dwa rzutowania pod rząd, żeby pobrać model, a potem żeby sobie wartość tego wiersza zgarnąć... bo ani event, ani modele nie mają pojęcia o tym, co trzymają. Więc tak - niestety dobrze zaprojektowany program jeśli będzie miał GUI, to rzutowaniami będzie tłukł ostro ;)

Ktoś coś wie o tym, czy jest w planach to kiedyś zgenerics'ować tak jak collections? Nie jestem na bieżąco.

No i ten potworek pokazuje też, że można - jak się jest durniem - napisać kod, który robi totalnie idiotyczne rzutowania (np Number na ImageIcon ;)) - i ani kompilator, ani runtime słowem nie piśnie. Uważać z rzutowaniami człowiek musi...

0

Ranides:
Za rok, dwa JavaFX 2 stanie się standardem i zastąpi wysłużonego Swinga.

1 użytkowników online, w tym zalogowanych: 0, gości: 1