如何从接口访问派生类成员? [英] How to access derived class members from an interface?
问题描述
我有三节课;实现接口IProduct的Stamp,Letter和Parcel,它们还具有一些自己的功能。
I have three classes; Stamp, Letter and Parcel that implement an interface IProduct and they also have some of their own functionality.
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; } }
}
为什么我不能访问派生的其他成员 List< IProduct>
吗?
Why can't I access the additional members of derived classes from a 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);
}
我考虑过使用泛型,但是在这种情况下,我将不得不单独编写每种特定类型产品的代码。
I thought of using generics, but in that case I will have to write separate code for each specific type of product.
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);
}
这种问题没有任何设计模式。
Isn't there any kind of design pattern for this kind of problem. Factory Pattern?
推荐答案
这是因为要在购物车中将每个购物车中的每个商品都作为IProduct投射到foreach循环中。您需要做的事情是这样的:
This is because you are casting each Item in the shopping cart as IProduct in your foreach loop. What you would need to do is something like:
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);
}
}
或者,这种更现代的语法现在在C#中可用,它结合了是
运算符,并带有变量声明:
Alternatively, this more modern syntax now available in C#, which combines the is
operator with the variable declaration:
foreach(IProduct product in ShoppingCart.Items)
{
if (product is Stamp stamp)
{
Console.WriteLine("Name: {0}, Quantity: {1}, Amount: {2}, UnitPrice: {3}", stamp.Name, stamp.Quantity, stamp.Amount, stamp.UnitPrice);
}
else if (product is Letter 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 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);
}
}
您还重复了不必要的属性名称,数量和金额。您应该从Product派生每个类:
Also you are repeating unnecessary properties Name, Quantity and Amount. You should derive each of your classes from Product:
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; }
}
这篇关于如何从接口访问派生类成员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!