Sto cercando di costruire un'architettura in C # e non riesco a trovare un modo per eseguire l'operazione. Fondamentalmente, c'è un insieme di classi A , B , C e D che ereditano da I . Ognuna di queste classi ha un'operazione Foo che opera su una delle altre classi e restituisce un oggetto di tipo R :
class A : I
{
public R Foo(A a);
public R Foo(B b);
public R Foo(C c);
public R Foo(D d);
}
class B : I
{
public R Foo(A a);
public R Foo(B b);
public R Foo(C c);
public R Foo(D d);
}
class C : I
{
public R Foo(A a);
public R Foo(B b);
public R Foo(C c);
public R Foo(D d);
}
class D : I
{
public R Foo(A a);
public R Foo(B b);
public R Foo(C c);
public R Foo(D d);
}
Questa operazione Foo è simmetrica (cioè a.Foo(b) == b.Foo(a) , d.Foo(a) == a.Foo(d) , ecc.). (Ovviamente, questo significa che dobbiamo solo definire Foo(A a) in A , Foo(A a) e Foo(B b) in B , e così via, ma tu hai l'idea).
Se introduciamo una nuova classe E , deve implementare Foo per tipi A , B , C , D e E .
class E : I
{
public R Foo(A a);
public R Foo(B b);
public R Foo(C c);
public R Foo(D d);
public R Foo(E e);
}
Ovviamente non possiamo aggiungere esternamente un'implementazione per public R Foo(E e) in ciascuna delle classi A , B , C e D (beh, non senza metodi di estensione), ma poiché Foo è simmetrico, a.Foo(e) == e.Foo(a) , quindi abbiamo solo bisogno di implementare Foo(A a) in E .
Ora, la parte che rende questo per me veramente difficile, è che c'è anche un oggetto "viewer" V che contiene un elenco di I . V deve essere in grado di eseguire l'operazione Foo tra due I 's senza conoscendo i loro tipi effettivi. V sa solo che l'operazione Foo esiste tra due I 's. In teoria, questo è come apparirebbe:
class V {
public R Foo(I i1, I i2)
{
// Check if i1 has an implementation for Foo taking
// the type of i2.
if (!i1.HasFoo(i2.GetType()))
{
// Do the same for i2 on i1.
if (!i2.HasFoo(i1.GetType()))
return null;
return i2.Foo(i1);
}
return i1.Foo(i2);
}
}
Ovviamente questo non funzionerebbe mai, per gli stessi motivi questo non funziona. Ci ho pensato per un po 'di tempo e non riesco a pensare a un'architettura che soddisfi queste esigenze in modo pulito. Ho ideato una serie di metodi contorti che abusano di tipi e schemi strategici e modelli di visitatori e dell'intero sh'bang, ma nulla che non sia soggetto a bug o eccessivamente complicato.
Come dovrei implementarlo, se è anche possibile?
Questa è l'applicazione reale, non astratta. È un motore di rilevamento delle collisioni, in cui le classi A , B , ecc. Sono diverse geometrie con proprietà fondamentalmente diverse (cerchio contro linea infinita vs poligono, ecc.). I diversi Foo s sono i diversi algoritmi che verificano se due forme geometriche si scontrano. V è un contenitore algoritmico per un gran numero di questi oggetti geometrici (un quadruplo o qualcosa del genere).