LINUX.ORG.RU

Прототипы — это не классы?:)

 , ,


0

1

Часто можно встретить такую вот бодягу, типа, в прототипном ООП нет классов, только прототипы. Это дает повод для спекуляций на тему того, что прототипное ООП чем-то уступает по мощности «классовому». А чем, собственно прототипы не классы? О чем вообще речь то ведется? Другое дело, что прототипы ничем не отличаются от объектов, кроме того, что имеют наследников. Никакой иной разницы тут нет.

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

Предлагаю, все таки, разобраться, раз и навсегда, отсутствие классов(на уровне сахара яп) — это баг, или фича?



Последнее исправление: fuckYankee (всего исправлений: 1)

спекуляций

Любитель копаться в чужих какахах?

winlook38 ★★
()

Это дает повод для спекуляций на тему того, что прототипное ООП чем-то уступает по мощности «классовому»

Нет, не даёт./thread

Deleted
()

Прототипы — нифига не классы. Делегирование — не наследование.

Что из этого лучше — совершенно другой вопрос. Но прототипы ведут себя сильно по-другому. На этом до сих пор спотыкается уйма привыкших к классам людей, когда они ВНЕЗАПНО обнаруживают, что в том же JS классов нет и даже class из ES6 ничерта не означает класс.

x3al ★★★★★
()

это баг, или фича?

Это особенности языка.

deep-purple ★★★★★
()
Ответ на: комментарий от x3al

Делегирование — не наследование

делегирование — это частный случай наследования. Другой случай — это копирование слотов. И то и другое прототипы позволяют.

Прототипы — нифига не классы

Ты можешь указать конкретную разницу, за исключением сахара?

fuckYankee
() автор топика
Ответ на: комментарий от fuckYankee

Ты можешь указать конкретную разницу, за исключением сахара?

Да запросто. Классы при наследовании становятся на 100% независимы от родителя. В том же JS связанные делегированием объекты остаются связанными, наследования нет, классов, собственно, тоже.

Я не говорю, что это хуже. Но не надо использовать устоявшиеся термины «класс» и «наследование» для того, что происходит в JS.

Можно говорить о «наследовании» и «классах» как паттернах, но опять же на уровне языка ни того, ни другого в lua/js нет.

Из этого ещё вытекает, что в прототипных языках нет «экземпляров класса» или инстанциации. Да, new в JS не имеет никакого отношения к new в языках с классами.

x3al ★★★★★
()
Ответ на: комментарий от x3al

В том же JS связанные делегированием объекты остаются связанными

Ну так ведь, делегирование то использовать никто не заставляет. Только это говнопаттерн конечно, хуже этого для построения архитектуры не придумаешь, никаких тебе метаобъектов, вся мощность Ъ сливается в унитаз.

Кстати, то что ты говоришь, не справедливо для Smаlltalk и Ruby, и даже отчасти для пистона и перла.

но опять же на уровне языка ни того, ни другого в lua/js

на уровне сахара нет, но не на уровне семантики.

Да, new в JS не имеет никакого отношения к new в языках с классами.

Почему?

fuckYankee
() автор топика
Ответ на: комментарий от fuckYankee

Ну так ведь, делегирование то использовать никто не заставляет.

Эмм. Так оно в язык встроено. Что class, что старые «конструктор-функции» (которые работают не как конструкторы в языках с классами) заточены под создание объектов, делегирующих всякую фигню типа-родителю (на деле он им нифига не родитель). prototype так работает.

Почему?

Потому, что в JS единственное, связывающее полученный после new объект с типа-родителем — делегирование через линк в prototype. И, естественно, эта связь не то, чтобы жёсткая. Объекты заметно динамичнее.

new — специальный способ вызова функции. Не метода. Не конструктора. Эта функция вообще никак не связана с классами (потому, что их в JS нет). Просто создаётся объект, слинкованный с её прототипом, и скармливается ей как this. Всё.

Да, это позволяет фокусы с .bind в рантайме (например, чтобы позаимствовать метод совершенно другого объекта). И доставляет немало проблем тем, кто не в курсе, как работает this.

Ну и я не помню языка с классами, позволяющего сменить родителя в рантайме. В JS родителей нет, соответственно, прототипную связь можно переключить куда угодно.

x3al ★★★★★
()
Ответ на: комментарий от x3al

Из всех классофич в ES6 единственный не-совсем-сахар — super (и extends в паре с ним). Но и super немного не такой, как в языках с классами.

x3al ★★★★★
()
Ответ на: комментарий от x3al

prototype так работает.

prototype юзать не обязытельно. Если ты не будешь его юзать, ты получишь то что ты хочешь — недоооп без метаобъектов.

Потому, что в JS единственное, связывающее полученный после new объект с типа-родителем — делегирование через линк в prototype. И, естественно, эта связь не то, чтобы жёсткая. Объекты заметно динамичнее

Ничего подобного. New инициализирует новый объект с собственными полями. Если у функции-инициализатора в прототипе стоит null, никакого делегирования у тебя вообще не будет, если дефолт — будет делегировать Object.

fuckYankee
() автор топика

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

https://en.wikipedia.org/wiki/Metaobject

/thread

loz ★★★★★
()
Ответ на: комментарий от fuckYankee

стоит null

пардон, чуть ошибся, так с new не получиться, только с Object.create. Это, BTW, косяк языка, конечно. Но, в любом случае, тебе никто не мешает наследоваться от верхнего объекта, который обычно никто не трогает.

Хотя вобще, new и все что с ним связано, это говно, лучше вообще забыть про него:)

fuckYankee
() автор топика
Ответ на: комментарий от fuckYankee

New инициализирует новый объект с собственными полями.

new инициализирует почти пустой объект, за вычетом прототипной связи. Никаких прочих полей у него нет. В случае ES6-сахара — поля (методы) будут у его прототипа. А собственные поля объекта в лучшем случае заполнит инициализатор.

у функции-инициализатора

в классовых языках такого нет. В JS любая функция — инициализатор просто потому, что new не сильно отличается от обычного вызова.

Если у функции-инициализатора в прототипе стоит null, никакого делегирования у тебя вообще не будет

Объект всё равно будет связан, пусть и с null.

Создать объект без делегирования через new нельзя. Можно через Object.create(null). Впрочем, если есть Object.create — можно забить на new вообще.

prototype юзать не обязытельно.

Так ничего больше и нету.

x3al ★★★★★
()
Ответ на: комментарий от loz

In computer science, a metaobject is an object that manipulates, creates, describes, or implements other objects (including itself). The object that the metaobject is about is called the base object. Some information that a metaobject might store is the base object's type, interface, class, methods, attributes, parse tree, etc. Metaobjects are examples of the computer science concept of reflection, where a system has access (usually at run time) to its internal structure. Reflection enables a system to essentially rewrite itself on the fly, to change the actual structure of the system as it executes.[1]

Это как то противоречит тому что я сказал? Да, сахар для классов, возможно, не ведет к тотальным ограничениям в таких языках как Smalltalk, однако это общей картины не меняет особо. Что же касается лиспа, clos, то не совсем понятно, что там вообще имеется в виду под «нативной» поддержкой. Видел пример лавсана на хабре, где он сначала костылит прототипное ООП, и только потом показывает, метаобъекты, уже в «нижнем» языке. Это называется нативно поддерживает?

fuckYankee
() автор топика

anonimous забанься обратно

Aswed ★★★★★
()
Ответ на: комментарий от x3al

new инициализирует почти пустой объект, за вычетом прототипной связи

Если ты реально думаешь, ты JS вообще не знаешь:) Это ошибка уровня суперзеленого новичка.

Объект всё равно будет связан, пусть и с null.

Это все равно, что делегирования у тебя вообще нет, тот же эффект.

Впрочем, если есть Object.create — можно забить на new вообще.

Это правда, я только за. New воняет жабой.

fuckYankee
() автор топика
Ответ на: комментарий от fuckYankee

Это как то противоречит тому что я сказал?

Да, первоклассные классы имеют протокол.

Да, сахар для классов, возможно, не ведет к тотальным ограничениям в таких языках как Smalltalk, однако это общей картины не меняет особо.

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

Что же касается лиспа, clos, то не совсем понятно, что там вообще имеется в виду под «нативной» поддержкой.

Это где такое написано?

loz ★★★★★
()
Ответ на: комментарий от fuckYankee

When a function is invoked with new in front of it, otherwise known as a constructor call, the following things are done automatically:

  1. a brand new object is created (aka, constructed) out of thin air
  2. the newly constructed object is [[Prototype]]-linked
  3. the newly constructed object is set as the this binding for that function call
  4. unless the function returns its own alternate object, the new-invoked function call will automatically return the newly constructed object.

ЧТД. Объект по new — пустой. Он потом линкуется с функцией-инициализатором и передаётся ей. Всё.

x3al ★★★★★
()
Ответ на: комментарий от x3al

Классы при наследовании становятся на 100% независимы от родителя.

В python тоже не становятся независимыми. Не надо java/плюсо реализацию считать единственно верной.

holuiitipun
()
Ответ на: комментарий от x3al

Ну и я не помню языка с классами, позволяющего сменить родителя в рантайме.

В python можно менять __class__.

holuiitipun
()

Прототипы это не классы, android это не iphone, linux это не windows, продолжать?

holuiitipun
()

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

anonymous
()

Тебя стоит снова забанить лишь за то, что пишешь совю фигню не в Web-development, а сюда. Ты когда пишешь свой бред, ты хотя бы теги свои читаешь то? Или просто копи-паст?

bookman900 ★★★★★
()
Ответ на: комментарий от loz

первоклассные классы имеют протокол.

В прототипном ООП любой объект является первоклассным классом.

Это где такое написано?

Ну, хз, как это понимать

The Common Lisp Object System (CLOS) came later and was influenced by the Smalltalk protocol. The CLOS model, unlike the Smalltalk model, allowed a class to have more than one superclass. This provides additional complexity in issues such as resolving which class has responsibility for handling messages defined on two different superclasses. One of the most influential books describing the metaobject protocol in CLOS was The Art of the Metaobject Protocol by Gregor Kiczales.[6]

Кстати, не знал, что в смоллтоке есть ограничение на количество суперклассов. Что-то он меня все больше и больше разочаровывает.

fuckYankee
() автор топика
Ответ на: комментарий от x3al

Объект по new — пустой

Он не пустой, он инициализирован новыми полями, конструктор его создает просто, далее он незвисим от конструктора, он просто слинкован будет с прототипом конструктора через свое __proto__

fuckYankee
() автор топика
Ответ на: комментарий от fuckYankee

В прототипном ООП любой объект является первоклассным классом.

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

Ну, хз, как это понимать

Тут просто написано что испытал влияние смолтолка и является более сложным в некоторых моментах.

loz ★★★★★
()

Прототипы - не классы. Даже классы - не классы. Напридумывали всякой херни, и друг друга понять не можем.

Debasher ★★★★★
()

Делаем ставки, через какое время автор будет снова забанен :)

ovk48 ★★★
()
Ответ на: комментарий от loz

Тут просто написано что испытал влияние смолтолка и является более сложным в некоторых моментах.

ИМХО, в том контексте, в котором тм говорится о сложности, тут как раз сложности никакой нет, неограниченное число суперклассов вполне естественно для метаобъектного подхода. Только я не пойму, действительно ли лисп поддерживает метаобъекты в полной мере, или это кукареканье. Что-то не попадалось мне на глаза четкого и ясного примера, код там обычно выглядит как нагромаждение левых костылей:)

fuckYankee
() автор топика
Ответ на: комментарий от loz

Но кажется что в общем случае они должны быть эквивалентны и реализовываться через друг друга.

Так оно и есть.

fuckYankee
() автор топика
Ответ на: комментарий от fuckYankee

Он не пустой, он инициализирован новыми полями

Нет, он пустой. Пока/если инициализатор (функция) не заполнит.

«Конструктор» ничерта ничего не создаёт. Объект создан до него. А инициализатор — инициализирует если он вообще в курсе того, что от него ждут.

x3al ★★★★★
()
Ответ на: комментарий от x3al

Нет, он пустой. Пока/если инициализатор (функция) не заполнит.

Ну, а с чем ты споришь тогда?

выражение new MyClass создаст новый объект и инициализирует его соответствующими полями. Он не будет «пустым» при выходе из него. Проверь уже на реальном движке. Или ты в демагогию вдарился. Сначала создает, а потом инициализирует, не означает, что конструкция возвращает пустой объект. Это синтаксис, ты мог бы его рассахарить и разбить на 2 части создание и инициализация (не считая возврата). Это обычная хрень. Ты в 2 соснах заблудился.

fuckYankee
() автор топика
Ответ на: комментарий от fuckYankee

выражение new MyClass создаст новый объект и инициализирует его соответствующими полями.

4.2.

MyClass — функция. Она может вернуть объект (никто не запрещал пользоваться return внутри функций). Знаешь, что станет с созданным до её вызова объектом в этом случае?

Знаешь что будет если функция MyClass уже жёстко связана с this и начихает на попытки его передать? И о том, чем отличаются способы жёстко связать (в Function.prototype.bind это — заранее предусмотренный special case)?

И да, я бы перестал притворяться, что MyClass — действительно класс.

x3al ★★★★★
()
Ответ на: комментарий от anonymous

Ребятам скучно, что ты хочешь. Вон, параллельно с «Царем» дрочатся довольно вменяемые люди, казалось бы, зачем?

Virtuos86 ★★★★★
()
Ответ на: комментарий от x3al

зачем ты тут рассказываешь, как кодер может сделать, неведомую (в том числе ему самому) х*ню? Какое это имеет отношение к делу? Ну я могу тоже сказать, а знаешь что будет, если ты напишешь foo, а эта foo не определена? Ух ты, ошибка будет, значит нету классов, железная логика.

fuckYankee
() автор топика

js
ЯП

Ты уж определись, JS или ЯП. Заодно и ответ будет.

t184256 ★★★★★
()
Ответ на: комментарий от x3al

MyClass уже жёстко связана с this и начихает на попытки его передать

Кстати, слово передать, в данном контексте, оксюморон. Там под капотом, грубо говоря, происходит


theConstructor.call(Object.create(Object.prototype))

fuckYankee
() автор топика

Другое дело, что прототипы ничем не отличаются от объектов, кроме того, что имеют наследников.

4.2. В классическом ООП класс - это объект, а наследование - посылка сообщения объекту-классу.

Современное ООП - не ООП, а прототипное ООП - вообще от лукавого.

Deleted
()
Последнее исправление: romeo250501 (всего исправлений: 1)
Ответ на: комментарий от Deleted

а наследование - посылка сообщения объекту-классу.

в каком смысле? в прототипном так оно и есть, только не посылка, а пересылка.

fuckYankee
() автор топика
Ответ на: комментарий от x3al

ну дык, у конструктора по дефолту стоит Object.create(Object.prototype), иными словами просто {}

fuckYankee
() автор топика
Ответ на: комментарий от fuckYankee

Только я не пойму, действительно ли лисп поддерживает метаобъекты в полной мере, или это кукареканье

Насколько я знаю CLOS реализован на CLOS. Подробнее можешь спросить где-нибудь на #lisp. Ну и вроде в AMOP описывается какое-то подмножество CLOS.

loz ★★★★★
()
Ответ на: комментарий от loz

Насколько я знаю CLOS реализован на CLOS

LOL, это бессмысленный базворд. Любой X может быть реализован на X (если X тьюринг полон, канешн), только всегда будет первый X который должен быть реализован на Y:)

fuckYankee
() автор топика

Дата регистрации: 26.08.2015 17:37:46
Форум 1

Для троллинга зарегистрировался что ли?

Deleted
()
Ответ на: комментарий от x3al

Ну и я не помню языка с классами, позволяющего сменить родителя в рантайме.

ЕМНИП, Objective-C.

Deleted
()
Ответ на: комментарий от Deleted

Да это наш старый пользователь anonimus или как-то так. Его банят раз в неделю, а он нового пользователя заводит.

peregrine ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.