Как мы можем избежать реализации избыточного интерфейса? - PullRequest
2 голосов
/ 29 апреля 2011

У меня есть вопрос дизайна.Я представлю гипотетическую ситуацию.У меня есть пара интерфейсов, необходимых моему приложению, чтобы сделать объект пригодным для использования.Допустим, они;

1.  IAdult.cs, with two properties
  a.    Age
  b.    LicenceNo.
2.  IEducated.cs, with two methods
  a.    Read()
  b.    Write()

Предположим, что реализация этих интерфейсов в большинстве случаев будет оставаться одинаковой.Поэтому, если бы нам пришлось реализовать абстрактный класс из этих интерфейсов, мы могли бы просто создать класс, скажем, абстрактный класс EducatedAdult {}.Теперь мы определяем три различных класса с их соответствующими наследованиями и набором соответствующих свойств;

1.  Carpenter.cs (derives from class A)
2.  Plumber.cs (derives from class B)
3.  Programmer.cs (derives from class C)

Здесь классы A, B, C являются частью некоторых внешних библиотек, которые я не могу редактировать.Теперь, чтобы сделать эти объекты пригодными для использования в Программе, им необходимо реализовать указанные выше интерфейсы.Таким образом, проблема заключается в том, что для каждого из этих классов мне придется явно реализовать вышеуказанные интерфейсы.Может ли быть лучший дизайн, где мне не нужно реализовывать интерфейсы избыточно во всех классах.Это могло бы быть решением, если бы это было возможно;

Class EducatedAdult<t>: t, IAdult, IEducated { <implementation of interfaces> } И позже, возможно, я мог бы просто инициализировать свои производные классы, как;Не то чтобы это было бы идеальным решением, потому что открытый интерфейс объекта carpenter по-прежнему не должен включать членов моего интерфейса (без обязательного приведения).Но тогда какой дизайн может быть наиболее подходящим?

Ответы [ 4 ]

1 голос
/ 29 апреля 2011

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

0 голосов
/ 30 апреля 2011

К сожалению, вы не можете сделать это в C # без какого-либо переписателя ассемблера или без использования dynamic.Вы можете сделать что-то похожее на mixin , но это изменит ваш дизайн.

Если вы можете использовать другой язык, Oxygene и Nemerle предложить функцию для реализации интерфейса, делегировав все его члены некоторому полю, которое также реализует интерфейс.

0 голосов
/ 29 апреля 2011

В вашем случае вы должны создать EducatedAdult как класс. Реализуйте все общие методы для ваших трех классов в EducatedAdult, как абстрактные другие, а затем реализуйте конкретные методы для каждого класса.

Увидимся

0 голосов
/ 29 апреля 2011

Хорошо, теперь, когда вы обновили свой вопрос:

Обновление : подход с наименьшим объемом работы, вероятно, будет следующим:

public interface IAdult { }
public interface IEducated { }

public static class Extensions
{
    // IAdult extensions
    public static void Age(this IAdult adult)
    {
        ...
    }

    public static void LicenseNo(this IAdult adult)
    {
        ...
    }

    // IEducated extensions
    public static void Read(this IEducated educated)
    {
        ...
    }

    public static void Write(this IEducated educated)
    {
        ...
    }
}

А затем пометьте свои классы пустыми интерфейсамипоэтому вам нечего реализовать

public class Carpenter : IAdult, IEducated
{
}

И вы можете использовать это так:

var carpenter = new Carpenter();
carpenter.Read();

И если вы хотите "переопределить" метод интерфейса, чтобы обеспечить другую реализацию, вы можетесделайте это:

public class Carpenter : IAdult, IEducated
{
    public void Read() { ... }
}

Когда вы вызываете Read() сейчас для объекта Carpenter, он будет использовать фактический метод Read() из класса Carpenter вместо метода расширения.Вы можете сделать это даже virtual и получить его из Carpenter и переопределить его в дочернем классе, как вы привыкли.Чтобы вызвать реализацию по умолчанию Read() в объекте Carpenter, вам нужно будет сделать Extensions.Read(this) вместо base.Read().

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