Как правильно преобразовать свойство родительского класса для вызова метода, специфичного для ребенка? - PullRequest
0 голосов
/ 01 мая 2019

Я сталкивался с этой проблемой несколько раз, и тот факт, что я не могу найти ответ, заставляет меня думать, что я делаю что-то странное на фундаментальном уровне, но здесь идет речь:

У меня естьабстрактный класс, который содержит свойство интерфейса (или абстрактного класса), которое определяет все общие методы, которые понадобятся любому дочернему элементу:

interface IFoo
{
    ...
}

abstract class Parent
{
    IFoo Foo { get; set; }
}

Затем у меня есть дочерний класс, который реализует этот абстрактный класс, и в егоконструктор, он устанавливает это свойство интерфейса в свою собственную реализацию:

class Child : Parent
{
    Child()
    {
       Foo = new ChildFoo();
    }
}

class ChildFoo : IFoo
{
    SomeMethod()
    {
    }
}

Проблема в том, что всякий раз, когда мне нужно вызвать SomeMethod () в Child, мне нужно сначала уменьшить Foo до ChildFoo.Должен ли я просто добавить свойство getter в Child, которое просто возвращает Foo как ChildFoo?Или я делаю что-то не так на фундаментальном уровне?

Редактировать:

Я прошу прощения за редактирование и за непринятие ответа (который на самом деле может стоять), но я чувствую, что должен былбыл более явным, потому что я все еще немного растерялся.

Parent и Child на самом деле являются контроллерами OData, а IFoo является интерфейсом сервисного уровня, который определяет основные методы CRUD.

Существует много дочерних контроллеров ODataВсе они содержат конечные точки для методов CRUD, определенных IFoo.Однако некоторые дочерние элементы также имеют конечные точки пользовательских функций, которые вызывают специфичные для сущности методы, которые не определены в IFoo.

Я надеялся избежать большого количества избыточного кода контроллера, поскольку все общие дочерние конечные точки вызывают универсальные методы.в родительском контроллере, используя свойство IFoo.Проблема в том, что я не могу вызвать специфичные для сущности методы в контроллере Child, не приведя IFoo к ChildFoo ().

Я начинаю думать, что мне следует просто полностью удалить родительский контроллер и добавить помощникакласс, который содержит методы с параметрами IFoo.

Извиняюсь, если я просто повторяюсь ..

Спасибо

Ответы [ 2 ]

2 голосов
/ 01 мая 2019

Вы делаете что-то не так на фундаментальном уровне. Вы устанавливаете Foo равным ChildFoo в конструкторе, но вы предоставляете средство получения свойств, в котором вы разрешаете любому установить его равным любому IFoo экземпляру.

Либо вам нужно убедиться, что никто никогда не сможет установить это свойство для чего-либо, кроме того, что ваш конструктор установил для него (сделав его только для чтения), и в этот момент вы можете безопасно гарантировать, что оно всегда будет ChildFoo (и в таком случае вы должны просто сохранить его в поле этого типа и иметь свойство только для чтения, возвращающее его, а не приводить его при каждом использовании). Или, если он должен быть настраиваемым извне, тогда IFoo явно нужен этот метод, потому что вам нужен любой экземпляр IFoo, чтобы иметь возможность выполнить эту операцию.

1 голос
/ 01 мая 2019

Одна фундаментальная проблема заключается в том, что если у вас есть IFoo, и вы преобразуете его в определенный класс, который реализует IFoo, например ChildFoo.

Точка интерфейса, такого как IFoo, заключается в том, что другой интерфейс имеет дело с интерфейсом, а не с конкретными типами, которые его реализуют. Если код в другом месте «знает», что IFoo действительно ChildFoo, то IFoo утратил причину существования.

  • Если ChildFoo является единственным классом, который реализует IFoo, тогда вам не нужен IFoo. (За исключением, возможно, модульного тестирования, но оно все равно не будет работать, если вы приведете интерфейс к конкретному типу.)
  • Если другие классы реализуют IFoo, то как вы узнаете, что данный IFoo является ChildFoo, а не каким-то другим классом, реализующим IFoo?
  • Даже если ChildFoo является единственным классом, который реализует IFoo сейчас, что, если другие классы реализуют IFoo позже?

Когда мы приводим интерфейс к чему-то, что его реализует, мы берем на себя обязательство отслеживать все эти детали, что рискованно и может привести к ошибкам во время выполнения.

Но мы также теряем одно из предполагаемых преимуществ интерфейсов, а именно то, что наш код зависит только от интерфейса, а не от конкретной реализации.

...