реализация по умолчанию интерфейса, который используется как отдельный компонент - PullRequest
0 голосов
/ 14 ноября 2011

У меня есть интерфейс IFoo, для которого я хочу предоставить реализацию по умолчанию Foo. Foo может использоваться как отдельный класс / компонент другими классами, которые реализуют IFoo.

IFoo используется несколькими классами, которые в основном реализуют его, перенаправляя вызовы в Foo, но для некоторых методов они могут предоставлять собственную реализацию.

Foo нужен доступ к (приватным) членам вызывающего класса.

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

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

Вопрос в том, что является хорошим дизайном для предоставления доступа Foo к этим членам или как это обычно достигается? Есть ли какие-либо известные шаблоны для этого?

РЕДАКТИРОВАТЬ: наследование не вариант, потому что классы, которые реализуют IFoo не могут наследовать от того же класса.

Ответы [ 3 ]

1 голос
/ 14 ноября 2011

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

interface IFoo {
    void MyMethod();
}

static class FooImp {
    public static void MyMethodImp(object private_object) {
        // ...
    }
}

class MyFoo : IFoo {
    public void MyMethod() {
        FooImp.MyMethodImp(m_PrivateObject);
    }
    object m_PrivateObject;
}

В качестве альтернативы, вы можете просто запомнить частные объекты в классе реализации и использовать композицию:

interface IFoo {
    void MyMethod();
}

static class FooImp {
    public FooImp(object private_object) {
        m_PrivateObject = private_object;
    }
    public void MyMethodImp() {
        // Use the m_PrivateObject somehow.
    }
    readonly object m_PrivateObject;
}

class MyFoo : IFoo {
    public MyFoo() {
        m_PrivateObject = ... ;
        m_FooImp = new FooImp(m_PrivateObject);
    }
    public void MyMethod() {
        m_FooImp.MyMethodImp();
    }
    object m_PrivateObject;
    readonly FooImp m_FooImp;
}

Конечно, идеальным решением было бы, если бы C # поддерживал множественное наследованиедля классов, а не только для интерфейсов, но это, к сожалению, не так.

1 голос
/ 14 ноября 2011

Нет наследства вы говорите? Так что в основном ваш класс Foo не должен реализовывать IFoo, он просто должен облегчить реализацию IFoo. Почему тогда вы не можете добавить некоторые параметры в методы? Примерно так:

ОК, посмотрим. Позвольте мне придумать несколько методов, чтобы убедиться, что я правильно понял:

interface IFoo
{
    void DisplayTime();
}

И ваш FooImplHelper (сделан статическим только для целей этого примера, я не знаю, имеет ли это смысл в вашем случае или нет)

public static FooImplHelper
{
    public static void DisplayTime(int UTFOffiset)
    {
        Console.WriteLine(DateTime.UtcNow + TimeSpan.FromHours(UTFOffset));
    }
}

и реализация IFoo

public class MyClock: BaseClock, IFoo
{
     public void DisplayTime()
     {
         FooImplHelper.DisplayTime(2);
     }
}

Имеет ли это смысл? Если нет, вам нужно будет предоставить больше информации.

Itay

0 голосов
/ 14 ноября 2011

Еще одна возможность, потому что вы попросили одну. Я предпочитаю первый, хотя.

Определите второй интерфейс:

 interface IFooImplHelper
 {
      int UTFOffset { get; }
 }

и создайте класс FooImpl следующим образом:

 class FooImpl: IFoo
 {
      private IFooImplHelper _helper;

      public FooImpl(IFooImplHelper helper)
      {
           _helper = helper;
      }

      public void DisplayTime()
      {
            Console.WriteLine(DateTime.UtcNow + TimeSpan.FromHours(_helper.UTFDifference);
      }
 }

Вашим клиентам потребуется реализовать интерфейс IFoo (переадресация вызовов в FooImpl) и интерфейс IFooImplHelper. Я действительно не думаю, что кто-то из них оценит дополнительную работу, хотя ...

Итай.

...