Re[7]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: · Великобритания  
Дата: 02.09.25 10:02
Оценка:
Здравствуйте, korvin_, Вы писали:

_>·>Так в данном случае это отличие динамической типизации и статической, а не особенности ООПшнсти. Во всяких Java вызов неизвестного метода просто не может произойти, т.к. такой код даже невалиден с т.з. компилятора.

_>ООПшность динамична по определению: только объект, в общем случае, знает какие сообщения он может обработать и как, а не компилятор.
Статическая типизация позволяет на этапе компиляции доказать, что объекту "посылаются сообщения" только те, которые он может обработать. Т.е. никакого "вызова неизвестного метода" просто быть не может.

_>Объект может находится в другом процессе, на другой машине. Во всяких Java через рефлексию можно попробовать вызывать любой метод у любого объекта. Во всяком случае можно было раньше. На этом строятся mock-фреймворки, AFAIK, и AOP-фреймворки (Aspect-Oriented Programming).

А рефлексия это уже реализация динамической типизации в рантайме, причём тут ООП? В каком-то смысле это просто до-компиляция кода уже после запуска.
Поэтому, в яп где нет рефлексии (в том же С++, например) — динамичности никакой нет, но отрицать наличие ООПшности в С++ у меня язык не повернётся.

_>·>А можно развернуть плз?

_>·>Как по мне, вызов метода — это частный случай отправки сообщения: синхронно, с получением результата, ровно одному получателю.
_>Сообщение -- это тоже объект, с ним можно делать всё то, что и с другими объектами, до, после, во время обработки. Методы -- это реакции на сообщения, практически просто вызов процедуры по указателю из VMT. Метод "принадлежит" объекту (классу, интерфейсу), сообщение -- нет, оно само по себе. Можно сохранить (в переменную) ссылку на метод (с объектом или без), но не параметры, либо сохранить замыкание с телом-вызовом метода.
Это вопрос интерпретации. Скажем, в Плюсах будет:

_>obj.Foo(x, y);
_>var objFooRef = obj.Foo;
//это объект типа std::function

_>objFooRef(x, y);
//Вызов метода с именем "operator()" с двумя арументами у объекта типа std::function.

Обычный делегат.

В java тоже нет ссылок на метод. Есть лямбды, которые в каком-то смысле просто реализации интерфейса:
var objFooRef = new Function() {
   R apply(X x, Y y) {return obj.Foo(x, y);}
}
//и даже приходится явно писать имя метода при вызове:
objFooRef.apply(x, y);
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 02.09.2025 10:03 · . Предыдущая версия .
Re[6]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: sergii.p  
Дата: 02.09.25 10:33
Оценка:
Здравствуйте, ·, Вы писали:

·>Как по мне, вызов метода — это частный случай отправки сообщения: синхронно, с получением результата, ровно одному получателю.


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

void consume_A(A & o) { o.f(); /* Здесь вызывается f из A */ }

void consume_B(B & o) { o.f(); /* Здесь вызывается f из B */ }


Конечно контекст может быть вложен в сообщение вручную, но тогда это ничем не отличается от вызова двух различных методов с разными именами.
Re[8]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: korvin_  
Дата: 02.09.25 11:25
Оценка:
Здравствуйте, ·, Вы писали:

·>Статическая типизация позволяет на этапе компиляции доказать, что объекту "посылаются сообщения" только те, которые он может обработать. Т.е. никакого "вызова неизвестного метода" просто быть не может.


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

·>А рефлексия это уже реализация динамической типизации в рантайме, причём тут ООП? В каком-то смысле это просто до-компиляция кода уже после запуска.

·>Поэтому, в яп где нет рефлексии (в том же С++, например) — динамичности никакой нет, но отрицать наличие ООПшности в С++ у меня язык не повернётся.

В C++ динамичность -- это косвенный вызов виртуального метода. Компилятор в общем случае не знает, какой код (реализация метода) будет вызван.

·>Это вопрос интерпретации. Скажем, в Плюсах будет:


·>
_>>obj.Foo(x, y);
_>>var objFooRef = obj.Foo;
·>//это объект типа std::function

_>>objFooRef(x, y);
·>//Вызов метода с именем "operator()" с двумя арументами у объекта типа std::function.
·>

·>Обычный делегат.

·>В java тоже нет ссылок на метод. Есть лямбды, которые в каком-то смысле просто реализации интерфейса:

·>
·>var objFooRef = new Function() {
·>   R apply(X x, Y y) {return obj.Foo(x, y);}
·>}
·>//и даже приходится явно писать имя метода при вызове:
·>objFooRef.apply(x, y);
·>


И ничто из этого не является сообщением, всё явно сводится к вызову процедуры (метода) по ссылке.
Re[9]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: so5team https://stiffstream.com
Дата: 02.09.25 11:49
Оценка:
Здравствуйте, korvin_, Вы писали:

_>В C++ динамичность -- это косвенный вызов виртуального метода. Компилятор в общем случае не знает, какой код (реализация метода) будет вызван.


Да вроде бы это не "динамичность", а "полиморфизм".

Компилятор точно знает, что вызывает A::f, но не знает что именно это будет за f.

Динамичность же появляется когда незвестно, имеем ли мы на руках объект типа A или же типа B, или же какого-то другого типа. Знаем только, что у этого объекта нужно вызвать f. Которого, в динамических языках, у объекта может и не быть.
Re[9]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: · Великобритания  
Дата: 02.09.25 11:53
Оценка:
Здравствуйте, korvin_, Вы писали:

_>·>Статическая типизация позволяет на этапе компиляции доказать, что объекту "посылаются сообщения" только те, которые он может обработать. Т.е. никакого "вызова неизвестного метода" просто быть не может.

_>Но это объекту решать, неизвестный метод или нет.
Ясен пень. Но вот как решать и в какой момент времени — это уже и есть разница между статикой и динамикой. Если объект решает это декларацией типа, явным определением списка методов compile-time, то это статика. Если в run-time — то динамика.

_>Объект может проглотить его молча, не вызывая исключение, проксировать сообщение какому-то другому объекту или объектам, или даже на лету создавать у себя какие-то свойства на основе информации о сообщении. Например, знакомый рассказывал, что в Ruby можно при чтении конфига из файла налету создавать свойства и аксессоры.

И что? Ruby же тоже динамический ЯП.
В java при чтении конфига можно хоть байт-код генерить налету, но ООП тут не при чём.

_>·>А рефлексия это уже реализация динамической типизации в рантайме, причём тут ООП? В каком-то смысле это просто до-компиляция кода уже после запуска.

_>·>Поэтому, в яп где нет рефлексии (в том же С++, например) — динамичности никакой нет, но отрицать наличие ООПшности в С++ у меня язык не повернётся.
_>В C++ динамичность -- это косвенный вызов виртуального метода. Компилятор в общем случае не знает, какой код (реализация метода) будет вызван.
Зато он точно знает, что некий метод будет вызван, с заранее известной сигнатурой. Причём тут "вызов неизвестного метода"?
Если тут и есть некая "динамичность", то она имеет совершенно другой смысл, чем твои "что в Ruby можно" и т.п.

_>И ничто из этого не является сообщением, всё явно сводится к вызову процедуры (метода) по ссылке.

В чём принципиальное отличие от синхронного сообщения с одним получателем?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: · Великобритания  
Дата: 02.09.25 12:03
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>·>Как по мне, вызов метода — это частный случай отправки сообщения: синхронно, с получением результата, ровно одному получателю.

SP>мне кажется ключевое, что мы теряем всю информацию о контексте выполнения. И тогда такие хотелки невозможно реализовать:
SP>
SP>void consume_A(A & o) { o.f(); /* Здесь вызывается f из A */ }
SP>void consume_B(B & o) { o.f(); /* Здесь вызывается f из B */ }
SP>

Честно скажу, что я очень сомневаюсь в оправданности таких хотелкок. И вообще с какого бодуна такие хотелки должны как-то улучшать ООПшность — хз.

В плюсах, кстати, такое можно через операторы преобразования типа реализовать, афаир, вместо наследования D от A и B.

SP>Конечно контекст может быть вложен в сообщение вручную, но тогда это ничем не отличается от вызова двух различных методов с разными именами.

Ну если в системе отправки сообщений как-то потребуется организовать требование "ровно одному получателю" — то так и получится.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: so5team https://stiffstream.com
Дата: 02.09.25 12:09
Оценка:
Здравствуйте, ·, Вы писали:

SP>>·>Как по мне, вызов метода — это частный случай отправки сообщения: синхронно, с получением результата, ровно одному получателю.

SP>>мне кажется ключевое, что мы теряем всю информацию о контексте выполнения. И тогда такие хотелки невозможно реализовать:
SP>>
SP>>void consume_A(A & o) { o.f(); /* Здесь вызывается f из A */ }
SP>>void consume_B(B & o) { o.f(); /* Здесь вызывается f из B */ }
SP>>

·>Честно скажу, что я очень сомневаюсь в оправданности таких хотелкок. И вообще с какого бодуна такие хотелки должны как-то улучшать ООПшность — хз.

Конкретно этот фрагмент -- это ни разу не хотелка, а обязательное требование к нормальному статически-типизированному языку: если у нас есть независимые интерфейсы A и B, то в consume_A нельзя передать ссылку на реализацию интерфейса B, а в consume_B -- нельзя передать ссылку на реализацию интерфейса A.

Дальше вопрос уходит в область того, а может ли какой-то тип D реализовывать сразу оба интерфейса.

Другое дело, что в известных мне динамически-типизированных языках показанное выше нельзя реализовать в принципе. Т.е. если у D есть метод f, но сам по себе D не является ни A, ни B (т.е. не выполняется отношение "is a"), то все равно ссылку на D можно пихнуть как в consume_A, так и в consume_B.
Re[9]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: · Великобритания  
Дата: 02.09.25 13:40
Оценка:
Здравствуйте, so5team, Вы писали:

S>Конкретно этот фрагмент -- это ни разу не хотелка, а обязательное требование к нормальному статически-типизированному языку: если у нас есть независимые интерфейсы A и B, то в consume_A нельзя передать ссылку на реализацию интерфейса B, а в consume_B -- нельзя передать ссылку на реализацию интерфейса A.

Эээ.. Погоди. С интерфейсами как раз всё в порядке. В интерфейсах нет никакого "f из A", т.к. A — это интерфейс и там никакой реализации быть не может. Там лишь декларация метода. Сама реализация будет в D.

S>Дальше вопрос уходит в область того, а может ли какой-то тип D реализовывать сразу оба интерфейса.

На самом деле твой вопрос ушел в область множественного наследования _реализаций_, а не интерфейсов.

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

S>Другое дело, что в известных мне динамически-типизированных языках показанное выше нельзя реализовать в принципе. Т.е. если у D есть метод f, но сам по себе D не является ни A, ни B (т.е. не выполняется отношение "is a"), то все равно ссылку на D можно пихнуть как в consume_A, так и в consume_B.

Начнём с того, а где там вообще будет D/A/B?? Не окажется ли, что там будет Object/Object/Object только?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 02.09.2025 13:43 · . Предыдущая версия . Еще …
Отредактировано 02.09.2025 13:42 · . Предыдущая версия .
Re[10]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: so5team https://stiffstream.com
Дата: 02.09.25 13:49
Оценка:
Здравствуйте, ·, Вы писали:

·>Эээ.. Погоди. С интерфейсами как раз всё в порядке. В интерфейсах нет никакого "f из A", т.к. A — это интерфейс


Как раз будет "f из A", а не "f из B".

·>Так вот такое множественное наследование, имхо, многие признают как вредный и сложный переусложнизм и отказываются от этой банки с червями.


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

S>>Другое дело, что в известных мне динамически-типизированных языках показанное выше нельзя реализовать в принципе.


·>Начнём с того, а где там вообще будет D/A/B??


Я именно это и сказал.
Re[12]: Недоучки по настоящему ООП не освоили (из-за Basic и С++)
От: B0FEE664  
Дата: 02.09.25 14:21
Оценка:
Здравствуйте, so5team, Вы писали:

S>Серьёзно я здесь вынужден говорить разве что о вашей альтернативной одаренности. О проблемах ОО-языков я здесь иронизирую. Но если вы настолько серьёзны, то покажите решение на C++ без костылей и нарушения условий задачи.


Так как проблемы никакой нет, то тут и показывать нечего. Если вам каким-то образом мешает именование методов и вы хотите полностью от них не зависеть, то используйте полиморфизм на основе signal-slot парадигмы, в которой любые объекты с любыми методами можно соединять, как вам хочется.
И каждый день — без права на ошибку...
Re[13]: Недоучки по настоящему ООП не освоили (из-за Basic и С++)
От: so5team https://stiffstream.com
Дата: 02.09.25 14:27
Оценка:
Здравствуйте, B0FEE664, Вы писали:

S>>Серьёзно я здесь вынужден говорить разве что о вашей альтернативной одаренности. О проблемах ОО-языков я здесь иронизирую. Но если вы настолько серьёзны, то покажите решение на C++ без костылей и нарушения условий задачи.


BFE>Так как проблемы никакой нет


Ну, когда слаще C++ ничего в распоряжении нет, то и проблемы нет, да.

Навелосипедить три разных варианта разной степени распущенности там, где в продуманных языках есть штатные средства для решения -- это настоящий крестовый подход. Таков путь, чё поделать-то.
Re[9]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: korvin_  
Дата: 02.09.25 14:28
Оценка:
Здравствуйте, so5team, Вы писали:

S>Конкретно этот фрагмент -- это ни разу не хотелка, а обязательное требование к нормальному статически-типизированному языку: если у нас есть независимые интерфейсы A и B, то в consume_A нельзя передать ссылку на реализацию интерфейса B, а в consume_B -- нельзя передать ссылку на реализацию интерфейса A.


Нет такого требования.

В некоторых языках реализован row polymorphism.

Реализовано для объектных типов в Ocaml, например

let printf = Printf.printf

class virtual a =
  object
    method virtual f : unit
  end

type b =
  <
    f : unit
  >

let consume_a (x : a) =
  printf "consume_A: " ;
  x #f ;
  print_newline ()

let consume_b (x : b) =
  printf "consume_B: " ;
  x #f ;
  print_newline ()

let consume_c (x : < f : unit ; .. >) =
  printf "consume_C: " ;
  x #f ;
  print_newline ()

class some_a =
  object
    method f =
      printf "some A object"
  end

let b =
  object
    method f =
      printf "object B"
  end

let main () =
  let a = new some_a in
  consume_a a ;
  consume_a b ;
  consume_b a ;
  consume_b b ;
  consume_c a ;
  consume_c b

let () = main ()


Примерно схожим образом работает утиная типизация интерфейсов в Go и протоколы/категории в Objective-C (вроде бы и в Swift тоже).
Отредактировано 02.09.2025 14:32 korvin_ . Предыдущая версия .
Re[11]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: · Великобритания  
Дата: 02.09.25 14:43
Оценка:
Здравствуйте, so5team, Вы писали:

S>·>Эээ.. Погоди. С интерфейсами как раз всё в порядке. В интерфейсах нет никакого "f из A", т.к. A — это интерфейс

S>Как раз будет "f из A", а не "f из B".
Я не понял твоё возражение. Суть в том, что в случае если А — интерфейс, то вызвать "f из A" ты не можешь, т.к. вызывать нечего. В интерфейсе кода нет. Там только декларация.

S>·>Так вот такое множественное наследование, имхо, многие признают как вредный и сложный переусложнизм и отказываются от этой банки с червями.

S>Да-да-да, миллионы мух не могут ошибаться. Да и значение косинуса в мирное время можно выбрать путем демократического голосования, а военное -- директивой главнокомандующего.
А по делу есть что сказать?

S>>>Другое дело, что в известных мне динамически-типизированных языках показанное выше нельзя реализовать в принципе.

S>·>Начнём с того, а где там вообще будет D/A/B??
S>Я именно это и сказал.
А в каких вообще известных тебе ЯП есть множественное наследование реализации? Ну кроме Плюсов.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[12]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: so5team https://stiffstream.com
Дата: 02.09.25 14:51
Оценка:
Здравствуйте, ·, Вы писали:

S>>·>Эээ.. Погоди. С интерфейсами как раз всё в порядке. В интерфейсах нет никакого "f из A", т.к. A — это интерфейс

S>>Как раз будет "f из A", а не "f из B".
·>Я не понял твоё возражение. Суть в том, что в случае если А — интерфейс, то вызвать "f из A" ты не можешь

Поскольку из интерфейса вызвать нельзя, то об этом вообще нет смысла говорить. За интерфейсом будет стоять реальный объект, который данный интерфейс реализует. А компилятор будет следить что это именно так.

·>А по делу есть что сказать?


Уже сказал: апелляция к мнению большинства идет лесом.

·>А в каких вообще известных тебе ЯП есть множественное наследование реализации? Ну кроме Плюсов.


Eiffel.
Re[10]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: so5team https://stiffstream.com
Дата: 02.09.25 14:52
Оценка:
Здравствуйте, korvin_, Вы писали:

_>Нет такого требования.


Есть.

_>В некоторых языках реализован row polymorphism.


А в некоторых и параметрический.

Я все же говорю об ООП. Ваше мнение о сферическом ООП в вакууме меня не интересует.
Re[11]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: korvin_  
Дата: 02.09.25 15:13
Оценка:
Здравствуйте, so5team, Вы писали:

S>Есть.


Нет. Как и нет никакого комитета, который его мог бы установить.

S>А в некоторых и параметрический.


И?

S>Я все же говорю об ООП. Ваше мнение о сферическом ООП в вакууме меня не интересует.


Мы тут все говорим об ООП, только вы говорите о каких-то деталях реализации, и ваши взгляды не является какой-либо истиной в последней инстанции.
Re[14]: Недоучки по настоящему ООП не освоили (из-за Basic и С++)
От: B0FEE664  
Дата: 02.09.25 16:35
Оценка:
Здравствуйте, so5team, Вы писали:

S>Ну, когда слаще C++ ничего в распоряжении нет, то и проблемы нет, да.

S>Навелосипедить три разных варианта разной степени распущенности там, где в продуманных языках есть штатные средства для решения -- это настоящий крестовый подход. Таков путь, чё поделать-то.

Да, в C/C++ отсутствует нормальная возможность задать второе имя для функции. Это очень, очень серьёзная проблема. Я много думал над этой проблемой и пришёл к выводу, что совершенно необходимо добавить возможность задавать имя в using-declaration в С++:
struct B
{
    virtual void f(int) { std::cout << "B::f\n"; }
};
 
struct D : B
{
    using B_f = B::f;
    void B_f(int) override { std::cout << "D::f\n"; } // D::B_f(int) overrides B::f(int)
}

После этого изменения C++ станет великолепным. Только эта маленькая правка отделяет C++ от идеального языка ООП !
И каждый день — без права на ошибку...
Re[15]: Недоучки по настоящему ООП не освоили (из-за Basic и С++)
От: so5team https://stiffstream.com
Дата: 03.09.25 04:05
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>После этого изменения C++ станет великолепным.


Шутки шутками, но т.к. C++ (пусть и в несколько кастрированном виде) комуниздит мегаполезные фичи из других языков (типа static if-а из D или Design By Contract из Eiffel), становясь при этом лучше, то может быть он когда-нибудь и возможность переименования позаимствует. И станет еще лучше.
Re[12]: Недоучки по настоящему ООП не освоили (из-за Basic и
От: so5team https://stiffstream.com
Дата: 03.09.25 04:11
Оценка:
Здравствуйте, korvin_, Вы писали:

S>>Есть.


_>Нет. Как и нет никакого комитета, который его мог бы установить.


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

S>>А в некоторых и параметрический.


_>И?


И это выходит за рамки темы ООП.

S>>Я все же говорю об ООП. Ваше мнение о сферическом ООП в вакууме меня не интересует.


_>Мы тут все говорим об ООП, только вы говорите о каких-то деталях реализации


Именно о деталях реализации. Я не ученый из области computer science и не занимаюсь развитием теорий.
Мое дело код писать. А код пишется на конкретных языках. А в конкретных языках конкретный ООП.
И программируя на C++ мне пофиг, какой ООП в SmallTalk, а программируя на Ruby мне пофиг, какой ООП в Eiffel, а программируя на Go мне пофиг, какой ООП в Java и т.д.

Поэтому с моей сугубо практической и потребительской точки зрения любые рассуждения о "настоящем ООП" -- это полная херня, над которой не грех и поиронизировать.

При этом некий шок вызывают персонажи, вроде вас, которые уходят в какие-то теории, не бьющиеся с окружающей меня объективной реальностью.
Re[3]: Недоучки по настоящему ООП не освоили (из-за Basic и С++)
От: Sinclair Россия https://github.com/evilguest/
Дата: 03.09.25 08:18
Оценка:
Здравствуйте, Shmj, Вы писали:

S>А по поводу настоящего ООП в Smalltalk и его превосходства над убогоньким недо-ООП из C++?

Про ST и ООП только на этом форуме было минимум два треда. С подробным обсуждением того, как Кей придумывал ООП, что в него закладывал, и как оно потом всё повернулось.

Кстати, в статье по ссылке нет ничего про превосходство ST.

Если у вас есть какой-то вопрос — то задайте его не в форме неверных утверждений, а в нормальной вопросительной форме. А ещё лучше — поищите ответ на него поиском по форуму.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.