Polimorfizm, interfejsy i klasy.

0

Mam klasę Point, która reprezentuje kartezjański układ współrzędnych do mojej gry.

W ramach nauki grę chcę napisać w kilku technologiach. Do tego nie chcę za każdym razem powtarzać kodu tak więc pomyślałem o polimorfizmie! Jednak napotkałem problem:

interface IPoint<T> where T : ValueType // Nie działa
T X { get; set; } // nie można ustawić modyfikatorów dostępu!
.
.
.
class Point<T> : IPoint<T> 
where T : ValueType // nie działa!

public T X {get;set; }// działa lecz
public T X {get; protected set } // nie działa!
// Działa gdy w IPoint jest tak:
T X {get;}
// wtedy
public T X {get; protected set; } // działa, ale nie wiem dlaczego i jakie to będzie miało skutki. 

// nie mogę dodać dwóch typów. W interfejsie nie można użyć operatorów więc w klasie:
public static Point<T> operator +(Point<T> p1, Point<T> p2)
... p1.X + p2.X // nie można dodać typów "T"! - dlatego, że nie są ustawione jako valuetype?  

I jeszcze jedno pytanie od strony projektowej.
Aplikacja będzie w konsoli, WPF, ASP.NET
tak więc cała logikę i "modele" chcę umieścić w osobnym projekcie.
Zrobić to jako bibliotekę .dll?

0

Nikt nie wie?

0
Krwawy Młot napisał(a):

Nikt nie wie?

Wrzuciłeś późnym wieczorem kawałek kodu w nieistniejącym języku i oczekujesz, że w ciągu kilkudziesięciu minut otrzymasz odpowiedź?!

Po prostu nie możesz użyć ValueType jako generic constraint. Język na to nie pozwala. Możesz użyć co najwyżej struct.

 public T X {get; protected set } // nie działa!

Oczywiście, że "nie działa", skoro w interfejsie wymagasz obu akcesorów publicznych.

public T X {get; protected set; } // działa, ale nie wiem dlaczego i jakie to będzie miało skutki. 

Jak to jakie? Będzie publiczny getter dostępny dla klientów tej klasy oraz jej interfejsu oraz setter dostępny dla klas potomnych.

p1.X + p2.X // nie można dodać typów "T"! - dlatego, że nie są ustawione jako valuetype?  

Nie, dlatego że typ właściwości X nie posiada operatora +.
Nie da się w C# zrobić generyczego ograniczenia na typy posiadające ten operator, bo nie ma wspólnej klasy/interffejsu definiującego ten operator. ValueType to nie jest typ bazowy dla typów liczbowych, a zdaje się, że tak chcesz go użyć.

tak więc cała logikę i "modele" chcę umieścić w osobnym projekcie.
Zrobić to jako bibliotekę .dll?

Tak.

0

Dzięki za odpowiedź.
Strasznie mnie to nurtuje i póki nie zrobię nie pójdę spać ;/

To w takim razie co mógłbym zrobić, żeby móc zaimplementować w klasach implementujących IPoint<T> operatory +, -, != i ==?

Ok więc .dll.
Jedno dodatkowe pytanko.
Domyślnie klasy operować będą na punktach w dwóch wymiarach kiedy indziej dodam trójwymiarowy.
W związku z tym stworzyć klasę Point<T> : IPoint<T> i z niej dziedziczyć kolejne czy do każda kolejna klasa ma implementować interfejs a później IPoint3D<T>?

0
Krwawy Młot napisał(a):

Dzięki za odpowiedź.
Strasznie mnie to nurtuje i póki nie zrobię nie pójdę spać ;/

No to wygląda na to, że nie pójdziesz, póki nie zmienisz specyfikacji języka i nie napiszesz do niego kompilatora. ;)
Tu jest artykuł nieco wyjaśniający, czemu tak jest: http://www.artima.com/intv/generics.html

To w takim razie co mógłbym zrobić, żeby móc zaimplementować w klasach implementujących IPoint<T> operatory +, -, != i ==?

Nic. Operatory to metody statyczne, a interfejs nie może deklarować metod statycznych.

Możesz mieć co najwyżej klasę abstrakcyjną, sprawdzać typ T w locie i rzucać wyjątkiem, jeśli nie jest int, long, double, itd., a w operatorze + rzucać argumenty na typ dynamic, aby móc je dodać. Ale to będzie brzydkie i niewydajne rozwiązanie. Najlepiej chyba napisać sobie specyficzne klasy, w ogóle olać generyczność w tym przypadku.

0

Nie no tak brzydko to nie może być.

W takim razie daruje sobie typy generyczne.

Zostaje jednak przy interfejsach. Mam więc w klasie Point implementującej IPoint

 
public static IPoint operator +(Point p1, Point p2)
{
return new Point(/*...*/);
}

oraz

 
public static bool operator ==(IPoint p1, IPoint p2)
{
return p1.GetHashCode() == p2.GetHashCode(); // I tutaj pytanie. Klasa Point przesłania bazowe GetHashCode więc które zostanie użyte? Z klasy object czy z klasy Point? 
}

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