E 'possibile rilevare l'abuso di passare l'argomento self-type in fase di compilazione?

0

Ho appena trovato il problema di base in OOP e non riesco a vedere alcuna soluzione funzionante, tranne il rinvio di un controllo appropriato fino al momento dell'esecuzione.

È una nozione abbastanza chiara di un'azione "fare qualcosa con valore dello stesso tipo", indipendentemente dal significato di un determinato linguaggio. Considera Equals in C # che nella forma più semplice è "questo oggetto è uguale a quell'oggetto". Oppure Comparable<T> anche in C #. Indipendentemente da dove inizi questa gerarchia, vale quanto segue:

Comparable<T> --> Animal --> Cat
                       +---> Dog

E il problema:

Animal cat = new Cat();
Animal dog = new Dog();
cat.Compare(dog); // ERR

Come progettare una lingua da zero in questo modo, che la riga precedente darebbe un errore in fase di compilazione?

Finora ho introdotto il tipo Self, che fornisce un chiaro significato a ciò che vorresti fare all'interno di un tipo:

type Animal ... compare(cmp Self) ... 
type Cat ... compare(cmp Self) ...
type Dog ... compare(cmp Self) ...

ma non è sufficiente per evitare il problema con oggetti che attraversano il passaggio.

Può essere fatto? Forse era già finito? Come?

Ho già considerato tali misure estreme come due tipi di metodi ereditari - con meccanismo virtuale e non - e li chiamano in modo appropriato, ma questo a sua volta esclude i tipi generici (a meno che i tipi generici non siano implementati come in C ++ - - come modelli). Con solo 2 livelli di ereditarietà si potrebbe fare proibendo l'uso del tipo di livello superiore eccetto per i vincoli generici - ovviamente è troppo limitante.

    
posta greenoldman 10.02.2016 - 18:43
fonte

1 risposta

3

Giusto per chiarire, IComparable<T> definisce che un oggetto ha un metodo CompareTo(T) che può essere chiamato.

Non richiede che l'oggetto (su cui è stato chiamato il metodo) e l'argomento (che è stato passato nel metodo) siano dello stesso tipo più derivato .

In generale, se chiami IComparable<T> tra Cat e Dog , dovrebbe restituire false.

Questo è coerente con il comportamento del non generico, non-interfaccia Object.Equals(Object) .

Infatti, se qualcuno passa in ((Animal)null) come argomento (null, come in non-esistenza , non ha un tipo più definito ), dato che il metodo target (l'oggetto su cui viene chiamato il metodo) non è nullo, dovrebbe restituire anche false.

Ci sono diversi approcci (non esaustivi). Queste non sono regole o linee guida: queste sono opzioni che chiunque può prendere in considerazione.

Approccio 1 (al momento della compilazione)

  • Animale non dovrebbe ereditare da una classe astratta Comparable .
    Di conseguenza, non sarebbe comparabile - avrebbe solo il metodo di base Object.Equals(Object) .
  • Invece, solo i tipi più derivati , ovvero Cat e Dog , dovrebbero implementare l'interfaccia corrispondente IComparable<Cat> e IComparable<Dog> , rispettivamente.
  • Ciò significa che non sarebbe possibile chiamare IComparable<T>.CompareTo(T) quando vengono date due istanze di Animal senza eseguire un confronto di tipo aggiuntivo (vedi sotto) e digitare cast.

Approccio 2 (in fase di esecuzione)

Utilizza il codice seguente come pre-condizione di confronto:

if (!left.GetType().Equals(right.GetType()))
{
    return false;
}
// followed by the normal comparison logic

Questo perché in C #, Object.GetType() restituisce il tipo di runtime dell'oggetto .

    
risposta data 10.02.2016 - 18:55
fonte

Leggi altre domande sui tag