Question

J'ai trois classes; Timbre, lettres et des colis qui mettent en œuvre une interface IProduct et ils ont aussi une partie de leur propre fonctionnalité.

public interface IProduct
{
    string Name { get; }
    int Quantity { get; set; }
    float Amount { get; }
}

public class Stamp : IProduct
{
    public string Name { get { return "Stamp"; } }
    public int Quantity { get; set; }
    public float Amount { get; set; }
    public float UnitPrice { get; set; }
}

public class Letter : IProduct
{
    public string Name { get { return "Letter"; } }
    public int Quantity { get; set; }        
    public float Amount { get; set; }
    public float Weight { get; set; }
    public string Destination { get; set; }
}

public class Parcel : IProduct
{
    public string Name { get { return "Parcel"; } }
    public int Quantity { get; set; }        
    public float Amount { get; set; }
    public float Weight { get; set; }
    public string Destination { get; set; }
    public int Size { get; set; }
}

public static class ShoppingCart
{
    private static List<IProduct> products = new List<IProduct>();
    public static List<IProduct> Items { get { return products; } }
}

Pourquoi ne puis-je accéder aux autres membres des classes dérivées d'un List<IProduct>?

ShoppingCart.Items.Add(new Stamp { Quantity = 5, UnitPrice = 10, Amount = 50 });
ShoppingCart.Items.Add(new Letter { Destination = "US", Quantity = 1, Weight = 3.5f });
ShoppingCart.Items.Add(new Parcel { Destination = "UK", Quantity = 3, Weight = 4.2f, Size = 5 });

foreach (IProduct product in ShoppingCart.Items)
{
    Console.WriteLine("Name: {0}, Quantity: {1}, Amount: {2}", product.Name, product.Quantity, product.Amount);
}

Je pensais que l'utilisation des médicaments génériques, mais dans ce cas je vais devoir écrire un code pour chaque type de produit spécifique.

public static class ShoppingCart<T> where T : IProduct
{
    private static List<T> items = new List<T>();
    public static List<T> Items { get { return items; } }
}


ShoppingCart<Stamp>.Items.Add(new Stamp { Quantity = 5, Amount = 10, UnitPrice = 50 });
ShoppingCart<Letter>.Items.Add(new Letter { Destination = "US", Quantity = 1, Weight = 3.5f });

foreach (Stamp s in ShoppingCart<Stamp>.Items)
{
    Console.WriteLine("Name: {0}, Quantity: {1}, Amount: {2}", s.Name, s.Quantity, s.Amount); 
}

foreach (Letter l in ShoppingCart<Letter>.Items)
{
    Console.WriteLine("Name: {0}, Destination: {1}, Weight: {2}", l.Name, l.Destination, l.Weight);      
}

est-il pas de type de modèle de conception pour ce genre de problème. Motif de l'usine?

Était-ce utile?

La solution

Ceci est parce que vous jettes chaque article dans le panier comme IProduct dans votre boucle foreach. Ce que vous devez faire est quelque chose comme:

foreach(IProduct product in ShoppingCart.Items)
{
    if (product is Stamp)
    {
        var stamp = product as Stamp;
        Console.WriteLine("Name: {0}, Quantity: {1}, Amount: {2}, UnitPrice: {3}", stamp.Name, stamp.Quantity, stamp.Amount, stamp.UnitPrice);
    }
    else if (product is Letter)
    {
        var letter = product as Letter;
        Console.WriteLine("Name: {0}, Quantity: {1}, Amount: {2}, Weight: {3}, Destination: {4}", letter.Name, letter.Quantity, letter.Amount, letter.Weight, letter.Destination);
    }
    else if (product is Parcel)
    {
        var parcel = product as Parcel;
        Console.WriteLine("Name: {0}, Quantity: {1}, Amount: {2}, Weight: {3}, Destination: {4}, Size: {5}", parcel.Name, parcel.Quantity, parcel.Amount, parcel.Weight, parcel.Destination, parcel.Size);
    }
}

vous aussi répéter des propriétés inutiles Nom, Quantité et montant . Vous devez tirer chacune de vos classes de produits:

public class Stamp: Product, IProduct
{
    public double UnitPrice { get; set; }
}

public class TransitProduct: Product, IProduct
{
    public double Weight { get; set; }
    public string Destination { get; set; }   
}

public class Letter: TransitProduct, IProduct
{
}

public class Parcel: TransitProduct, IProduct
{
    public double Size { get; set; }
}

Autres conseils

Vous ne pouvez pas accéder aux autres membres des classes qui implémentent une interface parce que vous êtes seulement d'exposer IProduct dans la liste des articles. Je rajouterais types de listes spécifiques pour chaque élément dans le panier à la classe ShoppingCart, et vous pouvez exposer une séquence de tous les produits dans le panier pour tout ce qui n'a besoin que d'utiliser l'interface IProduct:

public class ShoppingCart
{
    public IList<Stamp> Stamps { get; }
    public IList<Letter> Letters { get; }
    public IList<Parcel> Parcels { get; }

    public IEnumerable<IProduct> Products
    {
        get
        {
            return this.Stamps.Cast<IProduct>()
                .Concat(this.Letters.Cast<IProduct>())
                .Concat(this.Parcels.Cast<IProduct>());
        }
    }
}
  

Pourquoi ne puis-je accéder au plus   membres des classes dérivées d'une   List<IProduct>?

C'est parce que, interface IProduct ne connaît pas UnitPrice, etc Destination des propriétés de classe dérivée.

Vous essayez d'ajouter l'intelligence pour calculer la Amount à chacun de la classe dérivée des objets Stamp, lettres, des colis?

Alors, je dirais que vous avez besoin de redessiner un peu et utiliser le modèle de conception Décorateur .

DerivedClass::Amount()
{
  Base::Amount() + 
  //Amount logic based on derived class
}

La raison pour laquelle vous ne pouvez pas accéder à d'autres membres d'une classe dérivée est que vous utilisez l'interface dans la liste <> -. Par conséquent, vous ne pourrez accéder aux propriétés sur cette interface

Un modèle qui pourrait vous aider est le modèle à double expédition.

Exemple ci-dessous:

public interface IHandler
{
    void Handle(Stamp stamp);
    void Handle(Letter letter);
    ...
}

public class Handler : IHandler
{
    public void Handle(Stamp stamp)
    {
       // do some specific thing here...
    }
    public void Handle(Letter letter)
    {
       // do some specific thing here...
    }
    ...
}

public interface IProduct
{
    string Name { get; }
    int Quantity { get; set; }
    float Amount { get; }
    void Handle(IHandler handler);
}

public class Stamp : IProduct
{
    public string Name { get { return "Stamp"; } }
    public int Quantity { get; set; }
    public float Amount { get; set; }
    public float UnitPrice { get; set; }
    public void Handle(IHandler handler)
    {
         handler.Handle(this);
    }
}

Vous pouvez maintenant programmer certaines fonctionnalités spécifiques dans le gestionnaire - Je suppose que vous voulez calculer une sorte de prix total donné des choses telles que la quantité * prix unitaire ou une table de recherche de poids et destination ...

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top