1

私には2つの異なるブランドのネットカムの運用を管理する2つのクラスがあり、それぞれがまったく同じパブリックメンバーを持っていますが、プライベートメンバーは大きく異なります。それらのいずれかは、Paneクラス(実行時に決定されるタイプ)内にドッキングされます。Paneクラスは、追加の表示機能に加えて、ドッキングされているカメラの制御を提供します。アプリケーションがPaneクラスをインスタンス化し、ドッキングするカメラのタイプを指定する場合、Paneに適切なカメラクラスをインスタンス化させて、そのクラスを呼び出せるようにします。

私の問題は、このサンプルコードの最後の行に示されています...カメラは2つのCameraTypeタイプのいずれでもないObjectタイプであるため、カメラには.Start()メソッドがありません。

Pane.Start()がswitch / caseブロックで割り当てられたクラスのStart()メソッドを呼び出すように、設計時に割り当てられたクラスのメンバーを公開するように「オブジェクトカメラ」を取得するにはどうすればよいですか?

お時間をいただきありがとうございます、デイブ

public class CameraType1  //not to be used directly
{
    public CameraType1()
    {
        Stuff specific to this type of camera
    }

    public void Start()
    {
        // Stuff specific to starting a stream to this type
    }
}

public class CameraType2  //not to be used directly
{
    public CameraType2()
    {
        // Stuff specific to this type of camera
    }

    public void Start()
    {
        // Stuff specific to starting a stream to this type
    }
}

public class Pane
{
    object camera;

    public Pane(string CameraTypeToDeploy)
    {
        switch (CameraTypeToDeploy)
        {
            case "Type1":
                camera = new CameraType1();
                break;
            case "Type2":
                camera = new CameraType2();
                break;
        }
    }

    public void Start()
    {
        camera.Start();   //wrong... camera doesn't have a Start() method
    }
}
4

3 に答える 3

4

共通ベースタイプが必要です。すべてのカメラタイプが実装するインターフェイスを定義することも、すべてのカメラが継承する抽象的な基本タイプを作成することもできます。または、両方を作成できます。インターフェイスに対してプログラムし、インターフェイスを実装し、一般的に使用されるメンバーの実装を提供する基本クラスを提供します。

public interface ICamera
{
    string Name { get; }
    void Start();
}

public abstract class CameraBase : ICamera
{
    public abstract void Start(); // Needs to be overridden in non abstract classes.
    public virtual string Name { get; protected set; } // May be overridden.
}

public class CameraType1 : CameraBase
{
    public CameraType1()
    {
        // Stuff specific to this type of camera
        Name = "Type 1";
    }

    public override void Start()
    {
        // Stuff specific to starting a stream to this type
    }
}

public class CameraType2 : CameraBase
{
    public CameraType2()
    {
        // Stuff specific to this type of camera
        Name = "Type 2";
    }

    public override void Start()
    {
        // Stuff specific to starting a stream to this type
    }
}

public class Pane
{
    ICamera camera;

    public Pane(string CameraTypeToDeploy)
    {
        switch (CameraTypeToDeploy) {
            case "Type1":
                camera = new CameraType1();
                break;
            case "Type2":
                camera = new CameraType2();
                break;
        }
    }

    public void Start()
    {
        camera.Start();   //OK, all cameras have a Start() method
    }
}

インターフェイスは、優れた柔軟性と高度なデカップリングを提供します。ただし、再利用できる実装は提供されていません。

インターフェイスのない共通の基本クラス(抽象または非抽象)は、クラス間に高度な結合を作成しますが、すべての派生クラスのメンバーのすぐに使用できる実装を提供できます。

私の例に示すように、両方の利点を組み合わせることができます。カメラが他のすべてのカメラと大きく異なる場合でも、から派生せずに直接インターフェイスを実装するように決定できますCameraBase。当然のことながら、類似するカメラのさまざまなグループに対して複数のカメラ基本クラスを設定することもできます(たとえば、同様のAPIを使用する同じ会社のさまざまなカメラタイプ)。


更新#1

あなたのコメントによると、あなたのカメラクラスはベンダー提供の基本タイプから派生しています。あなたはまだ彼らにインターフェースを実装させることができます。

public class VendorSpecificCamera
{
    public string Name { get; } 
    public bool VendorSpecificStart(int mode, int framesPerSecond)
}

public class CameraType1 : VendorSpecificCamera, ICamera
{
    // The 'Name' property is inherited from the vendor specific base class and
    // is therefore already implemented in this example.

    public bool CameraStarted { get; private set; }

    public void Start()
    {
        CameraStarted = VendorSpecificStart(2, 25);
    }
}

ベンダータイプにインターフェイスメンバーのシグニチャと一致するメンバーがすでにある場合は、派生クラスで何もする必要はありません。そうでない場合は、不足しているメンバーを提供するだけです。


更新#2

ベンダー固有のカメラクラスを封印する必要がある場合、それから独自のクラスを派生させることはできません。次に、ベンダークラスの周りにラッパークラスを作成します

public class CameraType1 : ICamera
{
    private VendorSpecificCamera _camera;

    public CameraType1()
    {
        _camera = new VendorSpecificCamera();
    }

    public string Name { get { return _camera.Name; } } 

    public bool CameraStarted { get; private set; }

    public void Start()
    {
        CameraStarted = _camera.VendorSpecificStart(2, 25);
    }
}

読み取り専用プロパティを介してベンダー固有のカメラを表示して、ベンダー固有のプロパティにアクセスできるようにすることもできます。

public VendorSpecificCamera Camera { get { return _camera; } }
于 2012-12-10T20:17:15.353 に答える
3

両方にインターフェースを実装させますICamera

  public interface ICamera
  {
      void Start();
  } 

  public class Camera1 : ICamera 
  { 
       // your existing implementation 
  }

  public class Camera2 : ICamera 
  { 
       // your existing implementation 
  }

 public class Pane
 {
     ICamera camera;

     public Pane(string CameraTypeToDeploy)
     {
        // Your existing code
     }
     }

     public void Start()
     {
         camera.Start();   //ok, ICamera has a start method
     }
 }

インターフェイスは、複数のクラスが同じ機能を提供し、交換可能に使用できることをプログラムに伝える最も簡単な方法です。他のオプション(抽象クラ​​スまたは単純な継承)は、すべてをより混乱させる傾向がありますが、オプションである場合もあります。

于 2012-12-10T20:09:38.763 に答える
1

メソッドを含むインターフェースを作成し、.Start()両方を持ってCameraType1実装CameraType2します。そして、そのインターフェースのプロパティcameraを持ってPaneいます。

public Interface CameraType
{
    void Start();
}

public class CameraType1 : ICameraType  //not to be used directly
{
    public CameraType1()
    {
        Stuff specific to this type of camera
    }

    public void Start()
    {
        // Stuff specific to starting a stream to this type
    }
}

public class CameraType2 : ICameraType  //not to be used directly
{
    public CameraType2()
    {
        // Stuff specific to this type of camera
    }

    public void Start()
    {
        // Stuff specific to starting a stream to this type
    }
}

public class Pane
{
    ICameraType camera;

    public Pane(string CameraTypeToDeploy)
    {
        switch (CameraTypeToDeploy)
        {
            case "Type1":
                camera = new CameraType1();
                break;
            case "Type2":
                camera = new CameraType2();
                break;
        }
    }

    public void Start()
    {
        camera.Start(); 
    }
}
于 2012-12-10T20:15:13.853 に答える