2009-03-16 9 views
12

私はインターフェイスと抽象クラスを初めて使用しています。私はショッピングカートシステムのオブジェクトのためのコアメソッドと変数を定義するために、いくつかのインターフェースを作成したいと考えています。次に、コア関数を実装する抽象クラスを作成します。アイデアは、プロジェクトごとに若干異なる方法で他のクラスで使用できるということです。ここでインターフェイスメソッドの戻り値の型を別のインターフェイスとして定義するにはどうすればよいですか?

は私の(カットダウン)インターフェイスです:

public abstract class Cart : ICart 
{ 

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

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

そして、私のCartItem:

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

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

そしてここでは、イカールを実装して、私の抽象カートクラス(再び、唯一の関連する行を示す)でありますICartItemを実装するクラス:

私はクラスをコンパイルしようとするとエラーが発生するaying: 'Cart'はインターフェイスメンバー 'CartItems'を実装していません。 'Cart.CartItems'はSystem.Collections.Generic.Listの一致する戻り値の型がないため 'ICart.CartItems'を実装できません<ICartItem>。

私はここで考えているのは、インターフェイスがさまざまな方法でコア機能を実行し、新しいメソッドなどを追加する数多くのクラスによって実装できるということだと思っていました。なぜインターフェイスが実際に使用されているクラスそのクラスが実際にインターフェイスを正しく実装しているかぎりです。

答えて

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

ジェネリック医薬品は、これはこれを実装するためのかなり良い方法です#2.0 :) –

+0

Cから入手可能です! – mquander

+0

(C#2の問題を修正しました;あなたが気にしないことを願って) –

0

イカールはCartItemsのgetterとsetterを指定しますが、あなたの実装では、取得のみを持っています。

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

これはコントラ/共分散の問題です。

このコンパイルには2つの変更が必要です。

1)インターフェイスのプロパティで「set」オプションを削除します。 (それは取得のみを実装しています;プロパティ、どのような場合には、最も理にかなっている)

2)変更カートへ:

 
public abstract class Cart : ICart 
{

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

public List<ICartItem> CartItems 
{ ... 

また、私は非常にするIListを公開する代わりにするためにあなたのインターフェースを変更することはお勧めしリスト。デザインガイドライン(およびFxCop)では、パブリックインターフェイスでListを公開しないことを推奨しています。リストは実装の詳細です - IListは適切なインタフェース/戻り型です。

2

インターフェイスは契約です。あなたとあなたのクラスを使う人との間の契約。皆さんがICartインターフェイスを実装していることを伝えることで、インターフェイスのすべてのメソッドがクラスに存在することを約束しています。したがって、すべてのメソッドは、インタフェースメソッドのシグネチャと一致する必要があります。

ICartItemを実装している項目のリストを返すためには、DrJokepuが提案するようにジェネリックを使用する必要があります。これは、ICartItemを具体的に実装するのではなく、ICartItemを実装するオブジェクトのリストのみをインターフェイスに与えることを誰にも伝えます。

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

これを実行するには2つの方法があります。ジェネリックを使用するか、明示的にインターフェイスメンバーを実装することができます。

ジェネリック

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 
{ 
    ... 
} 
関連する問題