Вопрос наследования - объявление абстрактной и конкретной версий одного и того же свойства - PullRequest
0 голосов
/ 08 августа 2009

Хорошо, две альтернативы, но прежде чем я начну, вы должны знать это:

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 таким образом. Это действительно законный сценарий для сокрытия собственности?

Что бы вы выбрали и почему?

Или не стесняйтесь предлагать другие альтернативы.

Спасибо.

EDIT:

Следует отметить, что GatewayBase и ModelBase находятся в зависимой сборке, поэтому они ничего не знают о Gateway и Model. Однако, Gateway и Model, конечно, знают о GatewayBase и ModelBase.

Ответы [ 2 ]

2 голосов
/ 08 августа 2009

Вариант 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 .

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)
    {
    }
}
0 голосов
/ 08 августа 2009

Я не уверен, зачем вам второе свойство Gateway. Имеет ли Gateway интерфейс, отличный от GatewayBase? Если это так, я вижу разницу, но в целом я думаю, что это не лучший дизайн. Я бы серьезно подумал, должен ли Gateway предоставлять какие-либо другие свойства / методы, кроме GatewayBase. Если нет, то вам не нужно свойство Model.Gateway.

Хорошей идеей является использование наследования только в том случае, если между двумя классами существует отношение "Is A". Это означало бы, что Gateway "Is A" GatewayBase и должен обычно иметь те же свойства / методы, по крайней мере, которые являются общедоступными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...