代码之家  ›  专栏  ›  技术社区  ›  David Conlisk

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

  •  12
  • David Conlisk  · 技术社区  · 15 年前

    我不熟悉接口和抽象类。我想创建几个接口来为购物车系统的对象定义核心方法和变量。然后我要创建实现核心函数的抽象类。其思想是,对于不同的项目,其他类可以以稍微不同的方式使用它们。

    以下是我的(已删减的)接口:

    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;
            }
        }
    }
    

    以及实现icartitem的CartItem类:

    public abstract class CartItem : ICartItem
    {
        ...
    }
    

    当我试图编译这些类时,我得到一个错误消息:“cart”不实现接口成员“cartems”。cart.cartems“无法实现”icart.cartems“,因为它没有与system.collections.generic.list<icartitem>匹配的返回类型。

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

    6 回复  |  直到 8 年前
        1
  •  20
  •   Marc Gravell    15 年前

    您需要在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; }
    }
    
        2
  •  4
  •   Frederik Gheysels    15 年前

    在抽象类中,应定义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
    {
    }
    
        3
  •  3
  •   Reed Copsey    15 年前

    这是一个矛盾/协方差的问题。

    2进行此编译需要进行更改。

    1)删除接口属性上的“set”选项。(它只实现get;属性,在任何情况下都是最有意义的)

    2)将购物车更改为:

    public abstract class Cart : ICart
    {

    private List<CartItem> _cartItems = new List<CartItem>();
    
    public List<ICartItem> CartItems 
    { ...
    

    我还强烈建议更改接口以公开IList而不是列表。设计指南(和fxcop)建议不要在公共接口中公开列表。列表是一个实现细节-ilist是适当的接口/返回类型。

        4
  •  2
  •   Joel    15 年前

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

    以便返回 实施 iCartitem,您需要按照Drjokepu的建议使用泛型。这就告诉每个人,接口只提供实现iArtitem的对象列表,而不是具体实现iArtitem的对象列表。

    public interface ICart<T> where T : ICartItem
    {
        List<T> CartItems { get; set; }
    }
    
        5
  •  0
  •   Jamie Ide    15 年前

    icart为cartems指定getter和setter,但您的实现只有get。

        6
  •  0
  •   Eric    12 年前

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

    泛型

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