yigal_s: (Default)
[personal profile] yigal_s
Вроде, за долгие годы я так и не разобрался теоретицски, что такое Object Oriented и с чем его едят. Пытался читать всякие полу-популярные и полу-научные книги и статьи, но воз и ныне там.

Но вот что интересно. Нигде мне не встречалось упоминание одного нетривиального различия реализации типов в C++/java и, скажем, в Haskell, непосредественно касающегося OOP. В объектных языках вроде С++ отчего-то считается правильным передавать функции в качестве параметра ссылку(указатель) на интерфейс объекта, тем самым обеспечивая run-time полиморфизм. А между тем, сей подход в корне неверен недостаточен. Объекты могут реализовывать несколько интерфейсов, функция может нуждаться в нескольких интерфейсах объекта, опять же, поэтому адекватный способ полиморфной передачи объекта в типизированных языках - передача множества интерфейсов. Что, разумеется, желательно поддерживать на уровне самого языка, а не каких-нибудь темплейтных tuple-объектов. В отсутствие данного механизма в С++ приходится извращаться, придумывать связи между интерфейсами там, где их нет, наследовать один интерфейс от нескольких только лишь ради того, чтобы передавать такой композитный интерфейс в функции, упрощать и выхолащивать код, итд итп. Мне, кстати, вспоминается, что как-то я даже умудрился написать функцию, которой требовалось передавать два параметра - указателя на интерфейсы, которые указывали бы на один и тот же объект. От этого было рукой подать до понимания того, что это-то и есть принципиально-правильный способ работы с OOP полиморфизмом, но я как-то не докумекал тогда.

У меня, собсно, нет претезний к C++/java, но вот странно, что эта мысль мне нигде не встречалась. Сие демонстрирует, вообще-то, ужасающий деффицит адекватной, содержательной информации. Если, конечно, считать эту заметку адекватной и содержательной... )))

Date: 2017-05-23 03:03 pm (UTC)
lxe: (Default)
From: [personal profile] lxe
А чем параметры вызываемого метода не угодили? Хочется указать, какие из них фактически указывают на один и тот же экземпляр? А зачем методу это знать?

Date: 2017-05-23 03:58 pm (UTC)
lxe: (Default)
From: [personal profile] lxe
адекватный способ полиморфной передачи объекта в типизированных языках - передача множества интерфейсов. Что, разумеется, желательно поддерживать на уровне самого языка

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

Что еще "желательно поддерживать на уровне самого языка"?

Date: 2017-05-23 04:32 pm (UTC)
lxe: (Default)
From: [personal profile] lxe
Если для функции смешение типов в одной реализации принципиально, это не очень аккуратно написанная функция.

Но, вообще говоря, в Java есть возможность передать в функцию совместную реализацию нескольких интерфейсов. Или одного класса и нескольких интерфейсов. Без кортежов и без mix-ins. Рассказать, как?

Date: 2017-05-23 04:45 pm (UTC)
lxe: (Default)
From: [personal profile] lxe
public <E extends Employee & Taylor & Harvester & Piper> void hire(E employee) { /* ... */ }

Date: 2017-05-23 04:58 pm (UTC)
lxe: (Default)
From: [personal profile] lxe
Bounded generics with a[n upper] bound list.

Только, пожалуйста, когда так пишете, оставляйте overload с полным перечнем и зовите его насквозь. Синтаксический сахар - хорошо, но не все пьют с сахаром.

Date: 2017-05-23 04:55 pm (UTC)
lxe: (Default)
From: [personal profile] lxe
делая каждый интерфейс достаточно минимальным, зато передавая сразу несколько, если надо.

С точки зрения чистого design by contract, набирать спецификации сущностей из аспектов буквально по методу может быть удобно для разграничения полномочий вызываемого кода (можно, скажем, разрешить Фоме только читать из файла, а Ереме только писать), но в какой-то момент вам захочется обернуть один или два метода - и что тогда? Конечный реципиент, callee, будет тот же самый, а ссылки формально разные. Идентичность, повторюсь, это деталь имплементации. В какой-то момент привязка к ней взорвется, как взрываются downcasts.

Date: 2017-05-23 05:26 pm (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi
Ответ простой, на самом деле. Есть типы Черча и типы Карри. В типах Черча каждый объект имеет ровно один тип. Так устроен хаскель. В типах Карри объект может иметь сколько угодно типов, например, ноль. Так устроены языки с ООП. Черч не может ООП, потому что ты или двумерная точка, или трехмерная, но не одновременно. Если одно в другое вкладывается (или проектируется), то нужна функция. А в ООП пофиг, потому что.

Date: 2017-05-24 05:27 am (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi
Кому не угодила? Меня устраивает. Просто надо различать.