如何合理地实现类结构

时间:2016-01-29 13:43:28

标签: c#

我希望我的问题是合法的,因为我并没有真正习惯所有的等级类结构。

我尝试封装一个为连接到设备的两个不同摄像机提供相同功能的类。这些函数被认为是在类 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-Class上依赖DeviceObject的方法:

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

    Cam1.SomeFunction();
    Cam2.SomeFunction();
}

如果这是一个愚蠢的问题,我很抱歉,但经过7个小时的编程后,我完全陷入了困境,再也不知道了。)

更新:

我已经实现了 - 就像你们所有人推荐的那样 - 一个抽象基类,并将Camera Objects派生为基类的成员。

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

非常感谢所有帮助我的人,而不是让我下地狱:)

4 个答案:

答案 0 :(得分:2)

为什么不使用抽象类?

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

答案 1 :(得分:1)

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

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 - (或者最坏情况下使用私有设置器。

答案 2 :(得分:1)

正如其他人所建议的那样,你的问题的答案可能是添加一个摘要/覆盖:

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

但是,我是由HardwareDriver课程触发的。我想在这里提出两点:

  1. 驱动程序处理功能,而不是名称。如果您的目标是分解,您可能希望进行双重调度,根据范围调用内容。
  2. 相机的目的是什么?为什么它以“世界”的方式建模?作品?
  3. 双重发送

    让我们从双重调度开始。我看到它的方式,你可能最终会得到一个大型的开关#39;阻止包含逻辑的某个地方。这对我来说很有意义。基本上你可能试图将对象与逻辑分离 - 所以让我们使用继承来做到这一点。在这种情况下,它会像这样工作:

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

    我通过this的原因是因为您可能想要在HardwareDriver内调用另一个相机功能来进行魔术。

    以世界运作的方式进行建模

    如果两个相机没有任何共同点,那就不要给它们一个共同的基类。这毫无意义。

    或者更一般的规则:永远记住,班级模型并不需要对你作为一个人有意义;它必须对计算机有意义。

    如何知道您何时以错误方式运行

    2条线索:

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

答案 3 :(得分:0)

您可以使用封装方法接受DeviceObject的参数,如

public void CallSomeFunction(DeviceObject dobj) 
{
    dobj.SomeFunction();     
}

然后,您可以创建任何相机基类型的实例并调用方法

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