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).