Possiamo avere membri implicitamente digitati?

6

La tipizzazione implicita in lingue come C # consente verifiche del tipo in fase di compilazione senza necessariamente riferirsi a "direttamente" "in una classe di destinazione:

var toy = SantasWorkshop.Build();
toy.amuse();

In questo scenario, non abbiamo bisogno di sapere che tipo di toy è. Eppure, sappiamo ancora in fase di compilazione se la nostra toy non riesce a amuse() .

Tuttavia, questo è limitato all'ambito locale. Se vogliamo mettere quel toy in Stocking e mantenere i controlli in fase di compilazione, dobbiamo sapere qualcosa al riguardo in fase di compilazione, a parte la sua capacità di amuse() . Ad esempio, questo è illegale:

class Stocking {
  List<var> toys;
  public void add(var toy) {
    toys.add(toy);
  }
}

Se siamo disposti a sacrificare il controllo in fase di compilazione, le lingue come C # ci consentono di utilizzare digitazione dinamica :

class QuestionableLookingStocking {
  List<dynamic> toysIHope;
  public void add(dynamic toyIHope) {
    toysIHope.add(toyIHope);
  }
}

Ma questo ci permetterà di aggiungere oggetti a un QuestionableLookingStocking che potrebbe non essere effettivamente amuse() . E non lo sapremo fino a quando qualcuno non aggiungerà Coal in fase di runtime.

class Coal {
  public ChristmasMood ruinChristmas() {
    return new SadChristmas();
  }
}

Sarebbe logicamente possibile e fattibile estendere la digitazione implicita ai membri? Vale a dire, c'è qualche ragione per cui il compilatore non può lamentarsi se qualcuno prova a Stocking.add() un oggetto che non fa? t supportare le operazioni richieste da tutti i riferimenti a Stocking.toys[n] ?

Esistono pattern che possono simulare tipi di membri impliciti?

    
posta svidgen 20.12.2016 - 19:58
fonte

2 risposte

3

Puoi simulare tutto questo in C # usando i generici.

Questo codice è legale:

class Stocking<T> {
  List<T> toys;
  public void add(T toy) {
    toys.add(toy);
  }
}

E sono abbastanza sicuro che soddisfi tutti i tuoi obiettivi stabiliti: ottieni sicurezza del tipo in fase di compilazione su tutti i tuoi membri, e ogni giocattolo è un oggetto che supporta le operazioni richieste da tutti i riferimenti a Stocking.toys .

Naturalmente, non otterrai alcuna funzionalità aggiuntiva da ciascun giocattolo oltre a ciò che è già stato fornito dal tipo T , che probabilmente è ciò che stai veramente cercando. Che ne dici di provare qualcosa di simile:

public class Toy
{
    public string Name { get; set; }
}

public class Truck: Toy
{
    public void Dump()
    {
        Console.WriteLine("Dumping");
    }
}

public class Stocking<T>
{
    List<T> toys = new List<T>();
    public void Add(T toy)
    {
        toys.Add(toy);
    }
    public T Get(int index)
    {
        return toys[index];
    }
}

public class Program
{
    public static void Main(string[] args)
    {
        var s = new Stocking<Toy>();
        var t = new Truck() { Name = "Tonka" };

        s.Add(t);
        var toy = s.Get(0);

        // Generic Toy behavior
        Console.WriteLine(toy.Name);

        // Truck-specific behavior
        if (toy is Truck)
        {
            (toy as Truck).Dump();
        }
        Console.ReadLine();
    }
}

Questo codice emette

Tonka
Dumping

Che è esattamente quello che ti aspetteresti.

    
risposta data 20.12.2016 - 21:12
fonte
0

Per approfondire la risposta di Robert Harvey:

Non devi fermarti a Toy.

public class Possession
{
    public String Name {get; set;}

    public abstract void Use();
}

public class Toy : Possession
{
    public void Amuse()
    {
        Use();
    }
}

public class Truck : Toy
{
}

public class Dumptruck : Truck
{
    public override void Use()
    {
        Console.WriteLine("Dumping");
    }
}

public class Child
{
    public String Name {get; set;}
    public List<Possession> Owns;
    public List<Toy> Stocking;

    public void AddToStocking(Possession Item)
    {
        if (Item is Toy)
            Stocking.Add(Item);
        else
            throw new GrinchException($"{Item.Name} is not a toy, why are you trying to put it in {Name}'s stocking?");
    }
}
    
risposta data 21.12.2016 - 00:31
fonte

Leggi altre domande sui tag