C# 如何合理实施班级结构

C# 如何合理实施班级结构,c#,C#,我希望我的问题是正确的,因为我并不真正习惯所有的层次类结构 我试图封装一个类,该类为连接到设备的两个不同摄像头提供相同的函数。这些函数被认为是在类DeviceObject中,而我希望通过使用Camera1或Camera2的实例来访问这些函数。下面是一些可能不起作用的伪代码: public class Camera1 : DeviceObject { public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelec

我希望我的问题是正确的,因为我并不真正习惯所有的层次类结构

我试图封装一个类,该类为连接到设备的两个不同摄像头提供相同的函数。这些函数被认为是在类DeviceObject中,而我希望通过使用Camera1或Camera2的实例来访问这些函数。下面是一些可能不起作用的伪代码:

public class Camera1 : DeviceObject
{
    public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelect.CAM1;
}

public class Camera2 : DeviceObject
{
    public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelect.CAM2;
}

public class DeviceObject
{ 
    public void SomeFunction() 
    {
        HardwareDriver.Function(SelectedCamera);     
    }
}
我想要的是轻松访问依赖于Camera类的DeviceObject的方法:

public void Method() 
{
    Camera1 Cam1 = New Camera1();
    Camera2 Cam2 = New Camera2();

    Cam1.SomeFunction();
    Cam2.SomeFunction();
}
如果这是一个愚蠢的问题,我深表歉意,但经过7个小时的编程,我完全被卡住了,再也记不住了:)

更新: 我实现了一个抽象基类,并将摄影机对象派生为基类的成员,这完全是大家所推荐的

到目前为止我还不知道的是,可以将派生类强制转换为基类类型。这对我来说绝对是新鲜事,但却帮了我大忙!用我的实现

所以,感谢你们所有帮助我而又不让我下地狱的人:)

您可以有一个封装方法,它接受
DeviceObject
之类的参数

public void CallSomeFunction(DeviceObject dobj) 
{
    dobj.SomeFunction();     
}
然后,您可以创建任何摄影机基类型的实例并调用该方法

Camera1 Cam1 = New Camera1();
CallSomeFunction(cam1); 

您可以有一个封装方法,它接受
DeviceObject
like的参数

public void CallSomeFunction(DeviceObject dobj) 
{
    dobj.SomeFunction();     
}
然后,您可以创建任何摄影机基类型的实例并调用该方法

Camera1 Cam1 = New Camera1();
CallSomeFunction(cam1); 

为什么不使用抽象类呢

public class Camera1 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}

public class Camera2 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}

public abstract class Camera
{
    public abstract Generic.CameraSelect CameraType { get; set; }

    public void SomeFunction()
    {
        HardwareDriver.Function(this);
    }
}

为什么不使用抽象类呢

public class Camera1 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}

public class Camera2 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}

public abstract class Camera
{
    public abstract Generic.CameraSelect CameraType { get; set; }

    public void SomeFunction()
    {
        HardwareDriver.Function(this);
    }
}

通常仅当需要不同的实现(方法)时才使用继承。如果两个摄影机的实现相同,但所涉及的数据不同,则可以使用一个类和一个工厂来“创建”具有适当设置的摄影机

public class CameraFactory
{
    public static Camera1 {
    get {
        return new Camera {Camera = Generic.CameraSelect.CAM1};
    }

    public static Camera2 {
    get {
        return new Camera {Camera = Generic.CameraSelect.CAM2};
    }
}
这不是唯一的方法,但这是一种方法


还请注意,如果不应更改
Camera
属性,则将其设置为
get
-only(或最坏情况下使用私有setter)。

通常仅当需要不同的实现(方法)时才使用继承。如果两个摄像头的实现相同,但所涉及的数据不同,则可以使用一个类和一个工厂来“创建”具有适当设置的摄像头

public class CameraFactory
{
    public static Camera1 {
    get {
        return new Camera {Camera = Generic.CameraSelect.CAM1};
    }

    public static Camera2 {
    get {
        return new Camera {Camera = Generic.CameraSelect.CAM2};
    }
}
这不是唯一的方法,但这是一种方法


另外请注意,如果
摄像机
属性不应更改,则将其设置为
仅获取
(或者最坏情况下使用私人setter)。

正如其他人所建议的,您的问题的答案可能是添加一个抽象/覆盖:

public class Camera1 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}

public class Camera2 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}

public abstract class Camera
{
    public abstract Generic.CameraSelect CameraType { get; set; }

    public void SomeFunction()
    {
        HardwareDriver.Function(this);
    }
}
然而,我是被
硬件驱动程序
类触发的

  • 驱动程序工作于功能,而不是名称。如果您的目标是分解,那么您可能希望进行双重调度,根据范围调用内容
  • 相机的用途是什么?为什么它是以“世界”的工作方式建模的
  • 双重分派

    让我们从双重分派开始。在我看来,最终可能会在某个地方出现一个包含逻辑的大型“开关”块。这对我来说没有多大意义。基本上,您可能会尝试将对象与逻辑解耦——所以让我们使用继承来实现这一点。在这种情况下,它的工作原理如下:

    public class Camera1 : Camera
    {
        public override void SomeFunction(IDeviceVisitor driver)
        {
            // Very simple camera:
            driver.HandleAngle(this, 12.0);
            driver.GenerateModel();
        }
    }
    
    public class Camera2 : Camera
    {
        public override void SomeFunction(IDeviceVisitor driver)
        {
            // This camera understands focus
            driver.HandleAngle(this, 12.0);
            driver.HandleFocus(this, focus, this.focus * 1.2); 
            driver.GenerateModel();
        }   
    }
    
    public class SomeHardwareDriver : IDeviceVisitor { ... } 
    
    public interface IDeviceVisitor
    {
        void HandleFocus(Camera camera, double focusValue, double realDistance);
        void HandleAngle(Camera camera, double angle);
        void GenerateModel();
        // [...]
        // etc
    }
    
    public abstract class Camera
    {
        public abstract void SomeFunction(IDeviceVisitor driver);
    }
    
    我之所以传递
    这个
    ,是因为您可能想从
    硬件驱动程序中调用另一个摄像头函数来实现这个神奇的功能

    以世界运作的方式建模

    如果两个摄像头之间没有任何共同点,不要给它们一个共同的基类。这是没有意义的

    或者更一般的规则:始终记住,类模型不需要对您个人有意义;它必须对计算机有意义

    如何知道自己何时跑错了方向

    2条线索:

    • 如果你最终得到了大的开关块,大量的If-then-else等等,那么你可能做错了
    • 如果复制粘贴代码,可能是做错了

    正如其他人所建议的,您的问题的答案可能是添加一个抽象/覆盖:

    public class Camera1 : Camera
    {
        public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
    }
    
    public class Camera2 : Camera
    {
        public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
    }
    
    public abstract class Camera
    {
        public abstract Generic.CameraSelect CameraType { get; set; }
    
        public void SomeFunction()
        {
            HardwareDriver.Function(this);
        }
    }
    
    然而,我是被
    硬件驱动程序
    类触发的

  • 驱动程序工作于功能,而不是名称。如果您的目标是分解,那么您可能希望进行双重调度,根据范围调用内容
  • 相机的用途是什么?为什么它是以“世界”的工作方式建模的
  • 双重分派

    让我们从双重分派开始。在我看来,最终可能会在某个地方出现一个包含逻辑的大型“开关”块。这对我来说没有多大意义。基本上,您可能会尝试将对象与逻辑解耦——所以让我们使用继承来实现这一点。在这种情况下,它的工作原理如下:

    public class Camera1 : Camera
    {
        public override void SomeFunction(IDeviceVisitor driver)
        {
            // Very simple camera:
            driver.HandleAngle(this, 12.0);
            driver.GenerateModel();
        }
    }
    
    public class Camera2 : Camera
    {
        public override void SomeFunction(IDeviceVisitor driver)
        {
            // This camera understands focus
            driver.HandleAngle(this, 12.0);
            driver.HandleFocus(this, focus, this.focus * 1.2); 
            driver.GenerateModel();
        }   
    }
    
    public class SomeHardwareDriver : IDeviceVisitor { ... } 
    
    public interface IDeviceVisitor
    {
        void HandleFocus(Camera camera, double focusValue, double realDistance);
        void HandleAngle(Camera camera, double angle);
        void GenerateModel();
        // [...]
        // etc
    }
    
    public abstract class Camera
    {
        public abstract void SomeFunction(IDeviceVisitor driver);
    }
    
    我之所以传递
    这个
    ,是因为您可能想从
    硬件驱动程序中调用另一个摄像头函数来实现这个神奇的功能

    以世界运作的方式建模

    如果两个摄像头之间没有任何共同点,不要给它们一个共同的基类。这是没有意义的

    或者更一般的规则:始终记住,类模型不需要对您个人有意义;它必须对计算机有意义

    如何知道自己何时跑错了方向

    2条线索:

    • 如果你最终得到了大的开关块,大量的If-then-else等等,那么你可能做错了
    • 如果复制粘贴代码,可能是做错了

    你到底被困在哪里?我不太明白你想要实现什么。抽象方法的概念是你想要的吗?你到底被困在哪里?我不太明白你想要什么