dlaczego rzutowanie się nie udaje

Odpowiedz Nowy wątek
2011-08-22 16:19
0

Mam dwie klasy: klasaA i klasaB, przy czym klasaB dziedziczy z klasaA.
Następnie deklaruję obiekt klasy A.

klasaA k1 = new klasaA();

i chcę zrobić rzutowanie:

klasaB btest= k1;

to wyskakuje błąd

Error 2 Cannot implicitly convert type 'usingdll.Form1.klasaA' to 'usingdll.Form1.klasaB'. An explicit conversion exists (are you missing a cast?) E:\visual studio projects\projects\mydll\usingdll\Form1.cs 130 30 usingdll

co w moim rozumieniu znaczy, że potrzebne jest jawne (explicit) rzutowanie.
A kiedy rzutuję jawnie:

klasaB btest= (klasaB)k1;

to kompiluje się kod, ale kiedy dochodzi do linijki rzutowania, występuje
"błąd rzutowania".
Czy ktoś mi wytłumaczy co się dzieje wewnątrz takiego rzutowania, że się nie udaje?
Jak to rzutowanie przebiega wewnątrz klasy? Bardzo proszę o odpowiedzi.


"Wszystko co może być wynalezione, zostało wynalezione"
Charless H. Duell - komisarz urzędu patentowego U.S., 1899
edytowany 4x, ostatnio: madmike, 2011-08-22 18:04
Pokaż pozostałe 7 komentarzy
chcę wiedzieć aby rozumieć o co tu chodzi, mówienie "tak musi być" niczego nie wyjaśnia. Sprawdziłem to co mówił Zjarek a wiec btest is KlasaA wyszło true, ale k1 is KlasaB wyszło false. Nadal nie wiem jednak co robi rzutowanie... - maszynaz 2011-08-22 17:12
Ściągnij sobie kod źródłowy do mono i sprawdź. - Zjarek 2011-08-22 17:15
No dobra, załóżmy, że mamy klasę Zwierzę i Pies. Tworzysz sobie obiekt Zwierzę i rzutujesz na Pies. I czym właściwie teraz ma być ten zzrzutowany obiekt? Jakie pola powinien mieć wypełnione? Co z konstruktorem? Jest za dużo nieścisłości i "pytań", by defaultowo ot tak działało takie rzutowanie. - Rev 2011-08-22 17:15
A jeżeli jest to rzutowanie z klasy pochodnej na bazową, to jest duża szansa na to, że praktycznie nie robi ono nic. - Zjarek 2011-08-22 17:18
No, o to chodzi, by w gruncie rzeczy nic nie robiło. Pozwala na trzymanie obiektu klasy dziedziczonej jako typ klasy bazowej. Jedyny tego powód to elastyczność, możliwość trzymania tych obiektów razem. - Rev 2011-08-22 17:20

Pozostało 580 znaków

2011-08-22 18:03
0

Znalazłem coś takiego:

public class A
{
    public A() { }
}
 
public class B : A
{
    public B() { }
}

The new class—the derived class—then gains all the non-private data and behavior of the base class in addition to any other data or behaviors it defines for itself. The new class then has two effective types: the type of the new class and the type of the class it inherits.

In the example above, class B is effectively both B and A. When you access a B object, you can use the cast operation to convert it to an A object. The B object is not changed by the cast, but your view of the B object becomes restricted to A's data and behaviors. After casting a B to an A, that A can be cast back to a B. Not all instances of A can be cast to B—just those that are actually instances of B. If you access class B as a B type, you get both the class A and class B data and behaviors. The ability for an object to represent more than one type is called polymorphism.

Z tego można zrozumieć, że klasa dziedzicząca B jest zarówno klasą B i A, ale klasa A jest tylko klasą A. Kiedy się odwołuje do obiektu klasy B to można go przekształcić na obiekt klasy A. Obiekt klasy B się nie zmienia pod wpływem rzutowania, ale zmienia się widok, który zostaje ograniczony do pokazywania tylko danych obiektu klasy A i jego zachowań. Po rzutowaniu B na A można rzutować A na B, ale nie wszystkie instancje A mogą być rzutowane na B. Mogą tylko te, które są instancjami B. Kiedy się odwołuje do klasy B jako typu B dostaje się dane i zachowania klasy A i B. Zdolność obiektu do reprezentowania wiecej niz jednego typu jest nazywana polimorfizmem.


"Wszystko co może być wynalezione, zostało wynalezione"
Charless H. Duell - komisarz urzędu patentowego U.S., 1899
edytowany 2x, ostatnio: maszynaz, 2011-08-22 18:12
to mówi o tym samym, co ci do tej pory napisaliśmy. - Rev 2011-08-22 18:08

Pozostało 580 znaków

2011-08-22 18:18
1

Mówiąc krótko: możesz rzutować klasę B na klasę A, ponieważ klasa B zawiera wszystko co ma klasa A + to co rozszerza. W drugą stronę to nie przejdzie, ponieważ klasa A nie posiada elementów klasy B i mógłbyś chcieć odwołać się do nieistniejącej metody czy pola.

Ps. Czemu piszecie wszystko w komentarzach?

nie wiem :D - Rev 2011-08-22 18:21
zrozumiałem już, słowem kluczowym jest WIDOK. A więc rzutowanie to przełączanie widoku. Ponieważ B zawiera A i B to można zostawić na B lub przełączyć na A, ale odwrotnie z A nie da się przełączyć na B, bo A nie zawiera B. :D - maszynaz 2011-08-22 18:32
temat chyba wyczerpany... choć może ktoś jednak zna mechanizmy wewnętrzne... ;] - maszynaz 2011-08-22 18:34
Wewnętrzne? Znaczy jak to na poziomie bitów przebiega? - somekind 2011-08-22 19:02
mówiąc "wewnętrzne " chodzi mi o jakąś ukrytą metodę "public static explicit operator" jeśli takowa istnieje w tym przypadku ;> - maszynaz 2011-08-22 20:42

Pozostało 580 znaków

2011-08-23 00:26
0

To jest raczej pytanie o bebechy samego runtime, bo to on rozpoznaje, które bajty w pamięci należą do obiektu której klasy, a na podstawie kodu programu wie, co z nimi można zrobić.

W zasadzie nie ma sensu nigdy dokonywać takiego rzutowania. Jeśli rodzi się taka potrzeba, to znaczy, że projekt aplikacji jest zły - być może trzeba np. zastąpić dziedziczenie jakąś kompozycją.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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