我是接口和抽象类的新手。我想创建几个接口来定义购物车系统对象的核心方法和变量。然后我想创建实现核心功能的抽象类。这个想法是,其他类可以以不同的方式用于不同的项目。
以下是我的(简化)界面:
public interface ICart
{
...
List<ICartItem> CartItems { get; set; }
}
public interface ICartItem
{
int ProductId { get; set; }
int Quantity { get; set; }
}
这是我的抽象Cart类(再次,仅显示相关行),它实现了ICart:
public abstract class Cart : ICart
{
private List<CartItem> _cartItems = new List<CartItem>();
public List<CartItem> CartItems
{
get
{
return _cartItems;
}
}
}
我的CartItem类实现了ICartItem:
public abstract class CartItem : ICartItem
{
...
}
当我尝试编译类时,我得到一个错误说:'Cart'没有实现接口成员'CartItems'。 'Cart.CartItems'无法实现'ICart.CartItems',因为它没有匹配的返回类型System.Collections.Generic.List&lt; ICartItem&gt;。
我认为这里的想法是接口可以由许多类实现,这些类以不同的方式执行核心功能并添加新方法等。为什么我的接口需要知道实际使用的是什么类,只要该类实际上正确实现了接口?
答案 0 :(得分:20)
您需要在C#2中使用泛型来实现:
public interface ICart<T> where T : ICartItem
{
// ...
List<T> CartItems { get; set; }
}
public abstract class Cart : ICart<CartItem>
{
// ...
public List<CartItem> CartItems { get; set; }
}
答案 1 :(得分:4)
在抽象类中,您应该定义CartItems属性的返回类型,类型为List<ICartItem>
。
但是,如果你真的希望属性类型为List<CartItem>
,你可以这样做:
public interface ICart<TCartItem> where TCartItem : ICartItem
{
List<TCartItem> CartItems { get; set; }
}
public interface ICartItem
{
}
public abstract class Cart : ICart<CartItem>
{
public List<CartItem> { get; set; }
}
public abstract class CartItem : ICartItem
{
}
答案 2 :(得分:3)
这是对抗/协方差的问题。
进行此编译需要进行2次更改。
1)删除界面属性上的“set”选项。 (它只实现了get;属性,无论如何都是最有意义的)
2)将购物车更改为:
public abstract class Cart : ICart
{
private List<CartItem> _cartItems = new List<CartItem>();
public List<ICartItem> CartItems
{ ...
我还强烈建议您更改界面以公开IList而不是List。设计指南(和FxCop)建议不要在公共接口中公开List。 List是一个实现细节--IList是适当的接口/返回类型。
答案 3 :(得分:2)
接口是协议。如果您愿意,您和使用您班级的任何人之间的合同。通过告诉大家你正在实现ICart接口,你向他们保证接口中的所有方法都存在于你的类中。因此,所有方法都必须与接口方法的签名匹配。
为了返回实现 ICartItem的项目列表,您需要使用DrJokepu建议的泛型。这告诉大家,界面只能实现一个实现ICartItem的对象列表,而不是ICartItem。
public interface ICart<T> where T : ICartItem
{
List<T> CartItems { get; set; }
}
答案 4 :(得分:0)
ICart为CartItems指定了一个getter和setter,但是你的实现只有一个get。
答案 5 :(得分:0)
有两种方法可以实现这一目标。您可以使用泛型或显式实现接口成员。
泛型
public interface ICart<TCartItem> where TCartItem : ICartItem
{
...
List<TCartItem> CartItems { get; set; }
}
public interface ICartItem
{
int ProductId { get; set; }
int Quantity { get; set; }
}
public abstract class Cart : ICart<CartItem>
{
private List<CartItem> _cartItems = new List<CartItem>();
public List<CartItem> CartItems
{
get
{
return _cartItems;
}
}
}
public abstract class CartItem : ICartItem
{
...
}
明确实施的成员
public interface ICart
{
...
List<ICartItem> CartItems { get; set; }
}
public interface ICartItem
{
int ProductId { get; set; }
int Quantity { get; set; }
}
public abstract class Cart : ICart
{
private List<CartItem> _cartItems = new List<CartItem>();
List<ICartItem> ICart.CartItems
{
get
{
return CartItems;
}
}
public List<CartItem> CartItems
{
get
{
return _cartItems;
}
}
}
public abstract class CartItem : ICartItem
{
...
}