Можно ли наследовать пустой интерфейс? - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть этот обобщенный c метод:

        public void Send < TBiz, TEntity > (string serviceName, string pkName)
        where TEntity: class, IEntity
        where TBiz: class, BLL.Modules.INewSend 
        {
         var biz = DependencyFactory.Get < TBiz > ();
         var query = (biz.GetNotSent() as IEnumerable < TEntity > );
         NewSender < TBiz, TEntity > (serviceName, pkName, query);
        }

TEntity - это объекты моей модели данных (я имею в виду модель таблиц БД) и может быть любого типа (например, автомобили, люди, цветы). и так далее) но все они имеют свойство ID. TEntity реализует IEntity интерфейс. IEntity является пустым интерфейсом или может быть интерфейсом, который имеет только реализацию ID, как показано ниже:

public interface IEntity
{
}

или

public interface IEntity {
 public int ID {
  get;
  set;
 }
}

TBiz - это мой бизнес-класс, который реализует INewSend. INewSend - это простой интерфейс, который имеет 2 реализации:

public interface INewSend {
 void Send(long id, string userName);
 IEnumerable < IEntity > GetNotSent(); 
}

этот код работает нормально, но мне любопытно, что с точки зрения объектно-ориентированных принципов это нормально, что класс TEntity наследует интерфейс IEntity то есть пусто ? Я сделал это для того, чтобы передать разные классы (все эти классы наследуют интерфейс IEntity) в метод Send. Интерфейс IEntity также может быть интерфейсом со свойством ID, но я думаю, что это не меняет вопроса, поскольку сущности, реализующие этот интерфейс, имеют совершенно разные типы, хотя все они имеют свойство ID.

Ответы [ 2 ]

3 голосов
/ 27 февраля 2020

с точки зрения объектно-ориентированных принципов, это нормально, что класс TEntity наследует пустой интерфейс IEntity?

Не существует принципов ОО, которые бы указывали, что пустой интерфейс / пустой class / empty все, что еще было бы плохо или даже запрещено.

С точки зрения ОО, интерфейсы и классы обозначают (частичную) идентичность объекта. Следовательно, и интерфейс несет информацию сам по себе, независимо от того, является он или не пустым, то есть он определяет какие-либо элементы.

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

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

Чтобы иметь строго типизированный контракт метода GetNotSent, вам все равно придется предоставить хотя бы какой-нибудь тип общего предка. Будь то интерфейс (пустой или нет) или класс общего предка, зависит от вашего конкретного дизайна c.

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

Цель интерфейса - предоставить представление для «совершенно другого». типа». Следовательно, я бы попытался указать, каковы общие свойства, которые должны быть реализованы каждым классом, чтобы «быть сущностью», и выделить их в IEntity. Это имеет смысл. Затем интерфейс INewSend может использовать его и предоставить более согласованный контракт:

public interface INewSend 
{
    void Send(IEntity entity, string userName); // pass entity instead of its ID
    IEnumerable <IEntity> GetNotSent(); 
}

_Примечание: Ради примера я предположим что id, изначально передаваемый в Send, является идентификатором сущности.

0 голосов
/ 27 февраля 2020

Все нормально, иногда я использую пустой интерфейс только для классификации сущности.

...