Автор Тема: Маска вместо интерфейсов и базового класса  (Прочитано 30763 раз)

pygubanov

  • Newbie
  • *
  • Сообщений: 21
    • Просмотр профиля
Всем привет.
Задался таким вопросом существует ли в ООП "Маски" которые при наложении на объект возвращают, только то, что соответствует маске (методы, свойства...)?
Почему возник такой вопрос, если использовать наследование от интерфейса или абстрактного класса, то это накладывает на этапе проектирования ограничения на объекты.
Как я себе представляю действие маски. Допустим имеется два класса несвязанные между собой базовыми наследованием, применяя к ним маску мы получаем доступ к одинаково именованным методам и свойствам, которые соответствуют маске.
class A
{
 public string name;
 public void  Test(){}
...
}

class B
{
 public string name;
 public void  Test(){}
....
}


Накладываем маску

{
A a;
B b;
Mask1 mask;
mask = new Mask1(a);
mask.Test();
string name = mask.name;

mask = new Mask1(b);
mask.Test();
string name = mask.name;

List<A> listA;
List<B> listB;
TestForALL(MaskList(listA));
TestForALL(MaskList(listB));
}

....

void TestForALL(MaskList list)
{
 for (int i=0; i<list.Count; i++)
 {
   list[i].Test();
   string name =  list[i].name;
 }
}


Что скажите?

kkkk

  • Full Member
  • ***
  • Сообщений: 135
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #1 : Декабрь 12, 2016, 02:52:03 pm »
Цитировать
Допустим имеется два класса несвязанные между собой базовыми наследованием, применяя к ним маску мы получаем доступ к одинаково именованным методам и свойствам, которые соответствуют маске.
Так сделано в Go. То, что Вы называете маской, в Go называется всё-таки интерфейсом. Чтобы соответствовать интерфейсу тип должен воплощать методы интерфейса, но явной связи(наследования) не требуется. Единственная разница с Вашими масками в том, что из интерфейса доступны только методы, но этого достаточно.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #2 : Декабрь 12, 2016, 02:57:37 pm »
А если объектег не может то, что маска хочет? Что будет?
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #3 : Декабрь 12, 2016, 02:58:19 pm »
Цитировать
Допустим имеется два класса несвязанные между собой базовыми наследованием, применяя к ним маску мы получаем доступ к одинаково именованным методам и свойствам, которые соответствуют маске.
Так сделано в Go. То, что Вы называете маской, в Go называется всё-таки интерфейсом. Чтобы соответствовать интерфейсу тип должен воплощать методы интерфейса, но явной связи(наследования) не требуется. Единственная разница с Вашими масками в том, что из интерфейса доступны только методы, но этого достаточно.
Насколько я понимаю, тут хочется маски конструировать в рантайме. А это не интерфейсы уже. Но это всё легко достигается через рефлекшн.
Y = λf.(λx.f (x x)) (λx.f (x x))

pygubanov

  • Newbie
  • *
  • Сообщений: 21
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #4 : Декабрь 12, 2016, 04:50:09 pm »

Насколько я понимаю, тут хочется маски конструировать в рантайме. А это не интерфейсы уже. Но это всё легко достигается через рефлекшн.
[/quote]

в С# через рефлекшн это конечно можно сделать, но преимущество будет не то.

хочется не рантайм.  А даже вот такое через приведение типов Mask m = (Mask)a;
Только всё это повлечет большую вероятность сделать ошибки, а этого надо избегать (не давать технической возможности делать ошибки)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #5 : Декабрь 12, 2016, 04:53:04 pm »
в С# через рефлекшн это конечно можно сделать, но преимущество будет не то.

хочется не рантайм.  А даже вот такое через приведение типов Mask m = (Mask)a;
Только всё это повлечет большую вероятность сделать ошибки, а этого надо избегать (не давать технической возможности делать ошибки)
Погоди, тебе хочетяся плюсовых концептов да хаскельных type classes что ли? Т.е. хочется штуку которая к ООП вообще отношения не имеет.
Y = λf.(λx.f (x x)) (λx.f (x x))

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #6 : Декабрь 12, 2016, 08:11:05 pm »
Это же что-то типа структурной типизации. Вроде в каких-то ML-языках когда-то такое было, может и сейчас есть?

https://dzone.com/articles/duck-typing-scala-structural

Возможно, в питоне что-то такое есть, там же тоже "утиная типизация"...
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #7 : Декабрь 12, 2016, 09:32:07 pm »
Эта маска - и есть интерфейс как концепция.

А если объектег не может то, что маска хочет? Что будет?
Будет то же самое, что и при приведении объекта к типу, которому он не соответствует. Поэтому, в пару к операции приведения нужна операция проверки типа.

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

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #8 : Декабрь 12, 2016, 09:42:20 pm »
Эта маска - и есть интерфейс как концепция.

А если объектег не может то, что маска хочет? Что будет?
Будет то же самое, что и при приведении объекта к типу, которому он не соответствует. Поэтому, в пару к операции приведения нужна операция проверки типа.

Но в компилируемых языках (а точнее, в трансляторах, которые сопоставляют подпрограммы и их вызовы на этапе компиляции) такой способ работать не будет: в объектах разных классов порядок методов может различаться, и разное положение методов в разных виртуальных таблицах не позволит прозрачно пользоваться простым приведением.
Какие таблицы виртуальных функций? Тут же вообще нет нигде речи ни про наследование ни, следовательно, про ООП.
Y = λf.(λx.f (x x)) (λx.f (x x))

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #9 : Декабрь 12, 2016, 10:50:10 pm »
Какие таблицы виртуальных функций? Тут же вообще нет нигде речи ни про наследование ни, следовательно, про ООП.
Не очень понял... Я руководствовался этим:
Цитировать
существует ли в ООП "Маски" которые при наложении на объект возвращают, только то, что соответствует маске
...
два класса несвязанные между собой базовыми наследованием, применяя к ним маску мы получаем доступ к одинаково именованным методам и свойствам, которые соответствуют маске.
Или виртуальные - это исключительно абстрактные? Ну, тогда я имел в виду таблицу с указателями на реализованные методы.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #10 : Декабрь 13, 2016, 04:52:55 pm »
хочется не рантайм.  А даже вот такое через приведение типов Mask m = (Mask)a;
Только всё это повлечет большую вероятность сделать ошибки, а этого надо избегать (не давать технической возможности делать ошибки)

Мне кажется я делал что-то подобное. Может тебе подойдет такой подход:

Есть набор интерфейсов: I1, I2, ...In. Применительно к твоему случаю можно считать, что каждый интерефейс имеет всего один метод. Далее, ты декларируешь маску как набор интерфейсов:
typedef mask<I1, I3, I5> mask1;
typedef mask<I1, I3> mask2;

Далее эти маски используются на стыке подсистем:
ss1 make_subsystem1(mask1 const&);

Далее у тебя есть полная свобода откуда получить эту маску для передачи в подсистему: либо от объекта, реализующего необходимые интерфейсы, либо от другой маски, имеющей все необходимые интерфейсы. Корректность проверяется во время компиляции, работает в продакшине :)
class object1 : public I1, public I3
{
};

object1 o1;

mask2 m(o1); // OK, компилятор проверяет, что у o1 есть нужные интерфейсы
mask1 m(o1); // компилятор выдает ошибку - не хватвет интерфейса I5

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #11 : Декабрь 13, 2016, 04:56:06 pm »
Доступ к нужному интерфейсу выглядит так:
mask.get<I1>().method(); // здесь компилятор тоже все проверяет - есть такой интерфейс и у него есть такой метод

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #12 : Декабрь 13, 2016, 05:38:22 pm »
Еще хотел добавить: чисто технически на С++ можно реализовать маску как некий контейнер указателей на произольные методы произвольных объектов, которые можно вызывать со всеми необходимым гарантиями корректности типов. Но это будет сильно многословнее в использовании (как в месте декларации/инициализации такой маски так и в месте вызыва нужного метода), чем мой вариант с маской как контейнером ссылок на интерфейсы.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #13 : Декабрь 14, 2016, 11:14:09 pm »
Решение на модуле-2 (собираемое через gnu modula-2 compiler) работает похоже что корректно. Поэтому запустил прогон. И да, похоже comdiv выкатил новое решение которое снова самое быстрое. :-)

Через 3-4 часа будут результаты.
Y = λf.(λx.f (x x)) (λx.f (x x))

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Маска вместо интерфейсов и базового класса
« Ответ #14 : Декабрь 15, 2016, 05:20:15 am »
Решение на модуле-2 (собираемое через gnu modula-2 compiler) работает похоже что корректно. Поэтому запустил прогон. И да, похоже comdiv выкатил новое решение которое снова самое быстрое. :-)

Через 3-4 часа будут результаты.
Чота ты это не в той теме написал ))
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…