Zwrócenie typu pochodnej, a nie bazy - jak zrobić?

Odpowiedz Nowy wątek
2011-08-10 20:34
0

Witam! Napisałem klasę GameObject po której dziedziczą inne obiekty w grze. Mam klasę Player, która właśnie dziedziczy po GameObject. Mam też listę obiektów List<GameObject> objects. Tyle, że ta lista jest obsługiwana przez metodę innej klasy. W tej metodzie zwracam GameObject i przez to nie mam dostępu do pól Player. Jak wykonać rzutowanie czy może coś innego, aby zwróciło mi typ taki jaki jest na danej pozycji w liście. Kod:

 
        private List<GameObject> objects;
 
        public GameObject Get(int index)
        {
                return objects[index];
        }
 
        // --------------------------------
 
        GameObjectsManager.Get(123).Name // tu mam tylko pola GameObject, a chcę również pola Player

Co mam zrobić, żeby zwracało typ, o którym pisałem wcześniej (typ obiektu z listy o danym indexie)?


<error>There was an error during loading user signature. Please try to reboot the Universe and check again.</error>

Pozostało 580 znaków

2011-08-10 20:47
msm
0

Przede wszystkim po co Ci to :|. O to właśnie chodzi w dziedziczeniu że traktujesz obiekty jako klasę bazową. Jeśli chcesz rzutować zwrócony typ na Player to tylko na tej klasie będziesz mógł operować i równie dobrze możesz sobie dać spokój z całą tą obiektowością i dziedziczeniem...

Ale żeby nie było że nie piszę na temat:
Klasycznie:

((Player)GameObjectsManager.Get(123)).Name

Z użyciem operatora as:

(GameObjectsManager.Get(123) as Player).Name
edytowany 3x, ostatnio: madmike, 2011-08-10 20:51
Zapomniałeś o instanceof czy też jego odpowiedniku. - Wibowit 2011-08-10 21:07
instanceof brzmi is, ale przecież to nic nie rzutuje, tylko sprawdza. - Azarien 2011-08-10 21:34
Być może autorowi chodzi o to, że niektóre obiekty z tej listy są typu Player i chce je specjalnie obsłużyć. - Wibowit 2011-08-10 21:36

Pozostało 580 znaków

2011-08-11 09:09
0

Możesz użyć metody generycznej, żeby robiła rzutowanie jeszcze przed zwróceniem wartości. Chyba o takie rozwiązanie Ci chodziło.

Jak? Metoda ma w czasie kompilacji wykrywać czy element na indeksie 123 to Player? :] - msm 2011-08-11 10:46
To musi być określone przy wywołaniu metody. Jeżeli tego nie wiadomo, to jakiekolwiek rzutowanie nie ma sensu. - Sarrus 2011-08-11 10:52

Pozostało 580 znaków

2011-08-11 10:43
0

Ale skąd ja mam wiedzieć, że obiekt o indexie 25953 jest akurat np. Player? Równie dobrze to może być Building itd. I ja chcę właśnie pobrać ten obiekt takim jakim jest, a nie GameObject. Być może, że chodzi o to co post wyżej.

A ogólnie to skoro mam nie dziedziczyć każdego obiektu po GameObject to jak mam to zrobić?? Pisać oddzielnie każdą klasę, dla każdego obiektu, ciekawe jak zrobię z tego listę. Może jest jakiś sposób inny, to proszę o jego przedstawienie.


<error>There was an error during loading user signature. Please try to reboot the Universe and check again.</error>
edytowany 1x, ostatnio: xeo545x39, 2011-08-11 10:45

Pozostało 580 znaków

2011-08-11 10:54
0

Pytanie moje dlaczego to przechowujesz na jednej liście?

Ale skąd ja mam wiedzieć, że obiekt o indexie 25953 jest akurat np. Player? Równie dobrze to może być Building itd. I ja chcę właśnie pobrać ten obiekt takim jakim jest, a nie GameObject.

Jak chcesz mieć obiekt typu player odebrany z listy, to musisz wiedzieć, który to obiekt, albo zaimplementować w tej metodzie generycznej szukanie tego typu obiektów na liście (operator is)
EDIT:
To co tutaj proponuję jest tylko obejściem w przypadku gdy potrzebujesz trzymać te wszystkie obiekty na liście z innego (sensownego) powodu

edytowany 3x, ostatnio: Sarrus, 2011-08-11 11:53

Pozostało 580 znaków

2011-08-11 11:15
msm
0

A ogólnie to skoro mam nie dziedziczyć każdego obiektu po GameObject to jak mam to zrobić?? Pisać oddzielnie każdą klasę, dla każdego obiektu, ciekawe jak zrobię z tego listę. Może jest jakiś sposób inny, to proszę o jego przedstawienie.

Powinieneś dziedziczyć, nie masz rzutować. Po co Ci informacja że dany obiekt jest typu Player czy np. EvilDragon? Jeśli potrzebujesz pola Name to dodaj je do klasy bazowej.

edytowany 1x, ostatnio: msm, 2011-08-11 11:15
Zgadzam się w przypadku pola Name. Jeżeli jest to jednak właściwość IsStiupidPlayer, to już nie, bo nie o to w obiektowości chodzi, żeby klasa bazowa miała wszystko to co mają potomne ;) - Sarrus 2011-08-11 11:19
Tylko że jeśli w liście wszystkich graczy potrzeba sprawdzić czy ktoś jest graczem to coś jest prawdopodobnie nie tak - zresztą nie tylko w grach ale wszędzie w OO. Na przykład jeśli potrzebne jest to do zmienienia pozycji gracza to ja bym dodał wirtualną metodę abstract void Update(double delta); w klasie bazowej i nadpisywał w graczu (jako zmiana pozycji zależnie od stanu klawiatury) i np. przeciwniku (zmiana pozycji przez AI). A w miejscach gdzie trzeba mieć gracza (np. wyświetlenie HP w interfejsie) trzymał po prostu referencję do gracza a nie GameObject - msm 2011-08-11 11:37
Ogólnie dopóki nie wiadomo co autor chce zrobić to możemy tylko strzelać :> - msm 2011-08-11 11:38
A ogólnie Name jest w GameObject :] Może napisałem tak, że zrozumieliście, że jest w Player, ale nie jest. - xeo545x39 2011-08-11 13:10

Pozostało 580 znaków

2011-08-11 13:02
0

Ehh.. Myślę, że tak jest w większości gier więc tak zrobiłem. Mam listę obiektów w grze List<GameObject> klasa ma tylko pole i właściwość Name oraz metody abstrakcyjne Update i Draw. Wszystkie inne obiekty dziedziczą po GameObject. Myślałem czy Player'a dziedziczyć czy nie, żeby to było co innego w ogóle, ale postanowiłem dziedziczyć. Walić tego Player'a, bo to jednak trochę inna klasa. Ale co z obiektami np. Building, Vehicle itd. Przecież pojazd będzie miał pola np. prędkość, ilość miejsc itd. I chcę właśnie dostać się do tych pól (czy właściwości) poprzez mój GameObjectManager, który ma listę obiektów i ma metodę Get(int index) i Get(string name), które zwracają obiekt z listy. Jak mam napisać to wszystko, żeby ładnie się dodawało/usuwało/dostawało do tej listy obiektów. Nie zrobię przecież dla każdej klasy Vehicle etc. oddzielnej listy nie? A chcę dostać np. Vehicle (velocity, slots) + pola po GameObject (name) tyle, że jak wyszukuję po nazwie obiektu np. "Mercedes1", to zwraca mi GameObject, a ja chcę typ obiektu, który ma name = "Mercedes1". Czyli wyszukuję "mur_1342" i zwraca mi typ tego obiektu na liście czyli mur to może być building. Panimajesz?


<error>There was an error during loading user signature. Please try to reboot the Universe and check again.</error>

Pozostało 580 znaków

2011-08-11 13:22
0

Stosując moje obejście to wywołanie wyglądałoby mniej więcej tak:

Vehicle vehicle = objectManager.Get<Vehicle>("Mercedes1");

Pozostało 580 znaków

2011-08-11 13:31
msm
0

A stosując moje dwa:

Vehicle vehicle = (Vehicle)objectManager.Get("Mercedes1"); 
Vehicle vehicle = objectManager.Get("Mercedes1") as Vehicle;

Pozostało 580 znaków

2011-08-11 13:31
0

O w sumie dobre, nie pomyślałem (w sumie to chciałem tak zrobić, ale czytaj dalej), że można tak, ale to trochę psuje estetykę ;/ A jak zapobiec teraz, żebym sobie niechcący dał <vehicle>, a pod "Mercedes1" przypadkowo będzie inny typ?

I ogólnie brzydkie rozwiązanie, bo muszę pamiętać, jakiego typu jest to, to i tamto :( Żeby się kurde dało zwykłe Get i zwraca to co powinno ;/ Hehe:

public T Get(int index)
{
    return objects[i] as (object[i].GetType());
}

<error>There was an error during loading user signature. Please try to reboot the Universe and check again.</error>
edytowany 3x, ostatnio: xeo545x39, 2011-08-11 13:36

Pozostało 580 znaków

2011-08-11 13:34
msm
0

A jak zapobiec teraz, żebym sobie niechcący dał <vehicle>, a pod "Mercedes1" przypadkowo będzie inny typ?

Nie da się.

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