Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 继承问题-声明同一属性的抽象和具体版本_C#_Oop - Fatal编程技术网

C# 继承问题-声明同一属性的抽象和具体版本

C# 继承问题-声明同一属性的抽象和具体版本,c#,oop,C#,Oop,好的,有两种选择,但在我开始之前,您需要知道: public abstract class GatewayBase { ... } public class Gateway : GatewayBase { ... } 备选方案#1 public abstract class ModelBase { public GatewayBase GatewayBase { get; private set; } // property named GatewayBase publi

好的,有两种选择,但在我开始之前,您需要知道:

public abstract class GatewayBase { ... }

public class Gateway : GatewayBase { ... }

备选方案#1

public abstract class ModelBase
{
    public GatewayBase GatewayBase { get; private set; } // property named GatewayBase

    public ModelBase(GatewayBase gateway)
    {
        GatewayBase = gateway;
    }
}

public class Model : ModelBase
{
    public Gateway Gateway { get; private set; } // property named Gateway

    public Model(Gateway gateway)
        : base(gateway)
    {
        Gateway = gateway;
    }
}

备选方案2

public abstract class ModelBase
{
    public GatewayBase Gateway { get; private set; } // property named Gateway

    public ModelBase(GatewayBase gateway)
    {
        Gateway = gateway;
    }
}

public class Model : ModelBase
{
    public new Gateway Gateway { get; private set; } // property named Gateway plus "new" modifier

    public Model(Gateway gateway)
        : base(gateway)
    {
        Gateway = gateway;
    }
}

讨论:

public abstract class GatewayBase { ... }

public class Gateway : GatewayBase { ... }
使用备选方案#1,具体类
模型
可以“看到”网关的两个版本。一个称为
GatewayBase
,另一个称为just
Gateway
,但它们都包含完全相同的实例。对于备选方案#2,从技术上讲,
Gateway
仍有两个版本,但一个版本隐藏了另一个版本,因此实际上只有一个版本(除非使用
base.Gateway
绕过它)。我喜欢这个替代方案#2让我无论身在何处都可以调用属性
Gateway
,因为它在基本类和具体类中都被大量使用,而且它是一个简短但清晰的名称。尽管如此,我还是对以这种方式使用
new
修饰符有些犹豫。这真的是一个隐藏财产的合法场景吗

您会选择哪一种,为什么选择?

或者可以自由地提出其他选择

谢谢

编辑:

public abstract class GatewayBase { ... }

public class Gateway : GatewayBase { ... }

我应该提到,
GatewayBase
ModelBase
在一个依赖程序集中,因此它们对
Gateway
Model
一无所知。但是,
Gateway
Model
当然知道
GatewayBase
ModelBase

选项2看起来更干净,但不要创建单独的备份属性,而是通过将现有的基类属性从GatewayBase转换到Gateway来包装它。这样,您就不会对所使用的网关产生歧义:它总是相同的,只是从不同的角度:

public abstract class ModelBase
{
    public ModelBase(GatewayBase gateway)
    {
        this.Gateway = gateway;
    }

    public GatewayBase Gateway { get; private set; }
}

public class Model : ModelBase
{
    public Model(Gateway gateway)
        : base(gateway)
    {
    }

    public new Gateway { get { return (Gateway) base.Gateway; } }
}
您还可以使用泛型使不同类型的网关(有点像IEnumerable)更加灵活。泛型的问题是不能将一个C转换为另一个C(在4.0中有时可以)。解决这个问题的最干净的方法是引入一个非泛型接口,在泛型类上显式实现它。这样,当您与泛型实例交谈时,它就隐藏在视图之外,但您仍然可以混合使用C和C

公共接口IModel
{
GatewayBase网关{get;}
}
公共抽象类模型库:IModel
其中T:GatewayBase
{
公共模型库(TGateway网关)
{
this.Gateway=网关;
}
公用网关{get;专用集;}
GatewayBase IModel.Gateway{get{返回此.Gateway;}}
}
公共类模型:模型库
{
公共模型(网关)
:基本(网关)
{
}
}

我不确定您为什么想要第二个网关属性。网关是否具有与GatewayBase不同的接口?如果是这样的话,我看到了区别,但总的来说,我认为这可能不是最好的设计。我会认真考虑网关是否应该公开任何其他的属性/方法,而不是GatewayBase。如果不是,则不需要Model.Gateway属性


只有在两个类之间存在“is-a”关系时才使用继承是个好主意。这意味着Gateway“是”GatewayBase,通常应该具有相同的属性/方法,至少是公共属性/方法。

谢谢,鲁本。我真的很喜欢创建一个属性而不创建单独的支持属性的想法。使用泛型也很有趣,但我认为这比我在这个特殊情况下需要的要多一些。
Gateway
是一个带有附加功能的
GatewayBase
。这就像拥有一辆装有发动机、变速器和车轮的class
汽车和一辆装有发动机、变速器、车轮和涡轮增压器的class
FastCar:Car
。一辆快车就是一辆汽车——它能做汽车能做的一切,甚至更多。如果您有一个类
FastCarDriver
,其属性类型为
Car
(继承自
Driver
),则每次您想对涡轮增压器进行操作时,都需要进行强制转换。因此,如果
FastCarDriver
具有类型为
FastCar
的属性,这将非常方便。