C# rzutowanie dziedziczonego obiektu

0

Witam, mam problem z typem obiektu.

Stworzyłem sobie 2 klasy:

public class CSprite { /* ... */ }
public class CAnimation : CSprite  { /* ... */ }

Powyższa klasa reprezentuje obrazek. Potrzebuję odróżniać je od siebie, gdyż funkcja Draw() w dwóch przypadkach przybiera różne parametry.
(Do działania animacji potrzebuję dodatkowo przesłać informacje o czasie)

Oto jeden z konstruktorów klasy reprezentującej przeciwnika w grze:

public CEnemy(CSprite sprite, int health, float speed, int reward, int damage, CStage stage)
            : this()
        {
            this.m_sprite = new CSprite(sprite);
            this.m_health = m_maxhealth = health;
            this.m_speed = speed;
            this.m_stage = stage;
            this.m_sprite.m_position = stage.Way[0];
            this.m_target = stage.Way[1];
            this.m_reward = reward;
            this.m_damage = damage;
        }

this.m_sprite to oczywiście obrazek reprezentujący przeciwnika na ekranie. Gdy inicjuję konstruktor za pomocą obiektu CSprite, nie ma problemów, jednak gdy chcę to zrobić za pomocą obiektu CAnimation, konstruktor okraja go do CSprite...
Nie wiem jak zrobić, by obiekt mógł być typu CSprite, lub CAnimation.
Oto przykład

CEnemy przeciwnik = new CEnemy( new CAnimation animacja(), 1, 1f, 1, 1, new CStage()
if (przeciwnik.m_sprite.GetType() == typeof(CAnimation) ) //FALSE
	return;

Próbowałem mieszać w konstruktorach, pisać funkcję Copy(), na wiele różnych sposobów, ale nie mam pojęcia jak to zrobić. Trzeba rzutować obiekt?

0

(Do działania animacji potrzebuję dodatkowo przesłać informacje o czasie)

Bez bawienia się w żadne ify czy inne rzeczy, najlepiej będzie po prostu przesyłać także informację o czasie do CSprite, tak że będziesz miał metodę o tym samym nagłówku w obu klasach.

0
  1. CEnemy przeciwnik = new CEnemy(new CAnimation(), 1, 1f, 1, 1, new CStage());
  2. this.m_sprite = new CSprite(sprite); -> this.m_sprite = sprite.Clone(); // musisz zaimplementować IClonable np. jako funkcja abstrakcyjna lub wirtualna w sprite albo nie korzystaj z interfejsu i napisz swoje Clone najlepiej z nazwą DeepClone albo ShalowClone bo Clone to nigdy nie wiadomo co to jest - ważne, żeby Twoje klone było wirtualne i nadpisane w klasach pochodnych
0

Dzięki za odpowiedź, poradziłem sobie.
Stworzyłem funkcję klonującą:

public class CSprite{
/* ... */
	public virtual CSprite DeepCopy()
	{
		return new CSprite(this);
	}
}
/* ... */
public class CAnimation : CSprite
{
	public override CSprite DeepCopy()
	{
		return new CAnimation(this);
	}
}

Nie namęczyłem się przy niej, bo już wcześniej zadbałem o konstruktor kopiujący.
Wprowadziłem również parametr GameTime gameTime do funkcji Draw() w klasie CSprite. Jednak samo to nie wystarczyło, gdyż tak jak mówiłem, mój konstruktor okrajał obiekt z CAnimation do CSprite.
W konstruktorze oczywiście zmieniłem na this.m_sprite = sprite.DeepCopy();

Jeszcze raz dzięki :)

0

Moim skromnym zdaniem konstruktor kopiujący jest pod względem czytelności lepszym rozwiązaniem niż implementacja ICloneable (który nie ma nawet swojej generycznej wersji ze względu na olanie go przez MS). Podstawowe zalety to:
Jeżeli klasa dziedzicząca po klasie klonowalnej jest zbyt złożona żeby implementować jej klonowanie po prostu tego nie robimy.
Nie będziemy mieć sytuacji w której wywołamy Clone na Animation a otrzymamy Sprite (ponieważ ktoś nie nadpisał metody Clone)
Problemem w przypadku twojego kodu będzie fakt iż klonowanie trzeba będzie wykonać po za konstruktorem klasy Enemy (a dokładniej przed jego wywołaniem). Zaletą tego rozwiązania będzie możliwość kontrolowanego zmniejszenia zużycia pamięci (być może klonowanie nie zawsze ma sens).

0

@up, tyle ze nie zrobisz wirtualnego konstruktora

0

Moim zdaniem wcale mi on nie jest potrzebny. Dlaczego mam zakładać wewnątrz mojej klasy że nie mogę działać na obiekcie przekazanym mi jako parametr konstruktora i go z góry kopiuje (zwłaszcza gdy nie znam jego dokładnego typu)? wadą interfejsu ICloneable jest fakt iż zakłada kontrakt którego nie jesteśmy w stanie zapewnić w 100% (chyba że wszystkie nam znane klasy dziedziczące będą miały modyfikator final jak w przypadku klasy Brush)

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