繁体   English   中英

如何将接口方法的返回类型定义为另一个接口?

[英]How do I define the return type of an interface method to be another interface?

我是接口和抽象类的新手。 我想创建几个接口来为购物车系统的对象定义核心方法和变量。 然后我想创建实现核心功能的抽象类。 这个想法是它们可以被其他类以稍微不同的方式用于不同的项目。

这是我的(精简)界面:

public interface ICart
{
    ...
    List<ICartItem> CartItems { get; set; }
}

public interface ICartItem
{
    int ProductId { get; set; }
    int Quantity { get; set; }
}

这是我实现ICart的抽象购物车class(同样,只显示相关行):

public abstract class Cart : ICart
{

    private List<CartItem> _cartItems = new List<CartItem>();

    public List<CartItem> CartItems 
    {
        get
        {
            return _cartItems;
        }
    }
}

还有我的实现 ICartItem 的 CartItem class:

public abstract class CartItem : ICartItem
{
    ...
}

当我尝试编译这些类时,我收到一条错误消息:“Cart”没有实现接口成员“CartItems”。 “Cart.CartItems”无法实现“ICart.CartItems”,因为它没有 System.Collections.Generic.List<ICartItem> 的匹配返回类型。

我认为这里的想法是接口可以由许多类实现,这些类以不同的方式执行核心功能并添加新方法等。为什么我的接口需要知道 class 实际使用的是什么,只要因为 class 实际上正确实现了接口?

您需要在 C# 2 中使用 generics 来实现:

public interface ICart<T> where T : ICartItem
{
    // ...
    List<T> CartItems { get; set; }
}

public abstract class Cart : ICart<CartItem>
{
    // ...
    public List<CartItem> CartItems { get; set; }
}

在您的抽象 class 中,您应该定义 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 处更改。

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 是适当的接口/返回类型。

接口是一种协议。 如果您愿意,您与使用您的 class 的任何人之间的合同。 通过告诉人们您正在实现 ICart 接口,您向他们保证接口中的所有方法都存在于您的 class 上。 因此,您的所有方法都必须与接口方法的签名相匹配。

为了返回实现ICartItem 的项目列表,您需要按照 DrJokepu 的建议使用 generics。 这告诉大家,该接口只提供了一个实现 ICartItem 的对象列表,而不是具体的 ICartItem。

public interface ICart<T> where T : ICartItem
{
    List<T> CartItems { get; set; }
}

ICart 为 CartItems 指定了一个 getter 和 setter,但您的实现只有一个 get。

有两种方法可以做到这一点。 您可以使用 generics 或显式实现接口成员。

Generics

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
{
    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM