4

新しいプロジェクトのインターフェースを書いていますが、アドバイスが欲しいです。

サブクラスを持つクラスがあり、サブクラスがあります。このクラスのツリーは次のようになります。

Class Car
{
    Wheels Wheel;
}
Class Wheels
{
    Rims Rim;
}

簡単に言うと、1 台の車には 1 つのホイールがあり、1 つのホイールには 1 つのリムがあります。(他のより良い例を作ることはできません、申し訳ありません)。

そこで、ICar、IWheels、および IRim のインターフェイス実装でこの階層を強制したいと考えています。

だから私は(C#で)このようなことをしました:

ICar
{
  IWheels Wheel;
}
IWheels
{
  IRims Rim;
}

そして、インターフェイスの実装にフィールドを含めることができないというエラーがあります。これは、インターフェイスの設計が間違っているのではないかと思い始めました。インターフェイスの実装にこの種の階層の実装を強制したいと思います。しかし、デザイン パターンとベスト プラクティスに従って、別の方法で行う必要があるのではないでしょうか?

オブジェクトがこの種の階層を強制的に実装するようにシステムを設計する方法を教えてください。

私の質問に正確でないものがあるか、重要な情報が欠けている可能性があります。はいの場合は、コメントで質問してください。

4

6 に答える 6

10

インターフェイスの実装が持つべきフィールドを宣言できないため、インターフェイスでは、Wheels が ICar のプロパティであることを明確にする必要があります。(フィールドは内部の仕組みであるため、インターフェースはそれを認識すべきではありません)。

interface ICar
{
    IWheels Wheels
    {
       get;
    }
}
于 2009-06-26T13:38:59.277 に答える
7

インターフェースでフィールドを指定することはできません(そして、できるはずはありません - これは実装上の決定です) が、プロパティを指定することはできます:

public interface ICar
{
    IWheels Wheel { get; set; }
}

public interface IWheels
{
    IRims Rim { get; set; }
}

ただし、ゲッターのみをインターフェイスに配置することもできます。インターフェイスにセッターを含めるのは少し珍しいことです。

public interface ICar
{
    IWheels Wheel { get; }
}

public interface IWheels
{
    IRims Rim { get; }
}

(セッターを追加するためのゲッターしかない既存の (または抽象) プロパティをオーバーライドしたい場合は奇妙な点がありますが、セッターを使用して「ゲッターのみ」のインターフェイスを実装しても問題ないと思います。)

于 2009-06-26T13:39:35.783 に答える
4

エラーが示すように、インターフェイスでフィールドを指定することはできません。ただし、プロパティを指定できます。

interface ICar
{
    IWheels Wheel { get; set; }
}

interface IWheels
{
    IRims Rim { get; set; }
}
于 2009-06-26T13:39:29.073 に答える
4

フィールドは宣言できませんが、プロパティは宣言できます。これは、特定のクラスが別のクラスのインスタンスを提供することを強制するのと同じ最終効果があります。

ICar
{
  IWheels Wheel { get; set; }
}
IWheels
{
  IRims Rim { get; set; }
}
于 2009-06-26T13:39:40.353 に答える
0

私はC#にはあまり慣れていませんが、使用したいフィールドを使用して抽象クラスを作成することで、その実装を強制できるように思えます。したがって、これらの抽象クラスを拡張すると、それらのフィールドが使用可能になります。ただし、抽象クラスとインターフェイスを作成する必要があります...

于 2009-06-26T13:50:07.697 に答える
0

これは完全に機能するコードです...お役に立てば幸いです...

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication10
{
    //Interfaces

    public interface ICar
    {
        string name { get;}
        IWheel wheel { get;}
    }


    public interface IWheel
    {
        string brand { get;}
    }

    //Implementations

    public class Michelin : IWheel
    {
        #region IWheel Members

        public string brand
        {
            get { return "michelin"; }
        }

        #endregion
    }


    public class Toyota : ICar
    {
        Michelin m = new Michelin();
        #region ICar Members

        public string name
        {
            get { return "toyota"; }
        }

        public IWheel wheel
        {
            get { return m; }
        }

        #endregion
    }

    //A user of the interfaces. Only cares about ICar but knows implicitly about IWheel

    public class Stand
    {
        public Stand()
        {
            cars = new List<ICar>(2);
            cars.Add(new Toyota());
            cars.Add(new Toyota());
        }
        List<ICar> cars;

        public string ShowCars()
        {
            StringBuilder str = new StringBuilder();
            foreach (ICar iterCar in cars)
            {

                str.AppendLine(string.Format("car {0} with wheel {1}",
                    iterCar.name, iterCar.wheel.brand));
            }
            return str.ToString();
        }
    }

    //entry point. creates a stand and shows the cars, testing that properties are visible
    class Program
    {
        static void Main(string[] args)
        {
            Stand myLittleStand = new Stand();
            Console.WriteLine(myLittleStand.ShowCars());
        }
    }
}
于 2009-06-26T14:01:36.363 に答える