簡體   English   中英

繼承問題-聲明同一屬性的抽象和具體版本

[英]Inheritance question - declaring abstract and concrete versions of the same property

好的,有兩種選擇,但是在我開始之前,您需要了解這一點:

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

討論:

使用替代方法#1,具體的類Model可以“看到” Gateway兩個版本。 一個稱為GatewayBase ,另一個稱為Gateway ,但是它們都包含完全相同的實例。 從技術上講,使用替代方法2,仍然有兩個版本的Gateway但是一個版本隱藏了另一個版本,因此實際上只有一個版本(除非您使用base.Gateway繞過它)。 我喜歡替代方法2,無論我在哪里,都可以將其稱為Gateway屬性,因為它在基類和具體類中都得到了廣泛使用,並且它的名稱簡短但清晰。 盡管如此,我還是對以這種方式使用new修飾符有些猶豫。 這真的是隱藏財產的合理方案嗎?

您會選擇哪一個?為什么?

或隨時建議其他選擇。

謝謝。

編輯:

我應該指出, GatewayBaseModelBase是一個依賴程序集,所以他們不知道任何有關GatewayModel 然而, GatewayModel當然知道GatewayBaseModelBase

選項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 <T>)使事情變得更加靈活。 泛型的問題在於,您不能將一個C <X>轉換為另一個C <Y>(嗯,有時可以在4.0中轉換)。 解決此問題的最干凈方法是引入非泛型接口,您可以在泛型類上明確實現該接口。 這樣,當您與泛型實例通信時,它就不會顯示出來,但是您仍然可以混合使用C <X>和C <Y>。

public interface IModel
{
    GatewayBase Gateway { get; }
}

public abstract class ModelBase<TGateway> : IModel
    where T : GatewayBase
{
    public ModelBase(TGateway gateway)
    {
        this.Gateway = gateway;
    }

    public TGateway Gateway { get; private set; }

    GatewayBase IModel.Gateway { get { return this.Gateway; } }
}

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

我不確定為什么要第二個Gateway屬性。 網關是否具有與GatewayBase不同的接口? 如果是這樣,我會看到差異,但總的來說,我認為這可能不是最佳設計。 我會認真考慮網關是否應公開除GatewayBase之外的任何其他屬性/方法。 如果不是,則不需要Model.Gateway屬性。

最好僅在兩個類之間存在“是”關系時才使用繼承。 這意味着網關“是A” GatewayBase,並且通常應該具有相同的屬性/方法,至少是公共的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM