LINUX.ORG.RU

Что такое ООП

 ,


1

2

тут недвно был тред, что такое ооп, чем оно отличается от не-ооп, бла-бла-бла. Так ничего и не выяснилось толком.

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

Почему такой, казалось бы простой вопрос не имеет однозначного ответа?

Потому что ответ лежит на поверхности, поэтому его никто не видит.

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

Именно в этом и кроется разгадка того, почему так трудно отделить ООП от иных парадигм.

Простой пример. Возьмем подстановочную модель, ака ФП. Центральным объектом данной парадигмы является функция. С точки зрения ООП, функция — это актор. Например, у нас есть функция, которая имеет такой вид sum(1, 2) // 3 Мы могли бы выразить это как-то так

Sum = new Function
Sum.code = a + b
theSum = new Sum 
theSum.setArguments(a: 1, b: 2)
theSum.call

Это некоторая декомпозиция, которая нам показывает, что функция — это просто сахар объекта.

То есть, грубо говоря, если мы берем некоторую полноценную ООП/Акторную семантику, и ограничиваем ее выразительные возможности, мы получаем на выходе другую парадигму. Такие вот дела:)



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

Ответ на: комментарий от monk

Потому что в ООП метод определяется первым аргументом. А в примере g (x, y) зависит от типа y.

ну так чо тебе мешает этот y ставить первым в своем выражении? Было g(x, y) стало y g(x). Разница тут ровно такая же как между инфиксной и префиксной записью.

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

Точно так же ООП выражается в функциональном виде, если передать объект дополнительным аргументом.

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

Потому что в ООП метод определяется первым аргументом.

CLOS, обобщенные функции же, ты чего.

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

если передать объект

вот именно, что объект. Синтаксис тут второстепнен, он не имеет значения. Однако, если ты имеешь дело с объектами — значит у тебя ООП, независимо от расстановки скобок. Вызов функции в глобальном пространстве имен — это сообщение отправленное глобальному объекту, при этом отправителем может быть он сам.

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

А что ты думаешь о неделе высокой моды, прошедшей в Лондоне в сентябре? Кстати какой там синоним к слову «лопать» и perjuicio это по-испански «предрассудок». Подумай об этом.

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

Хотел уже начать спорить, посмотрел определение в вики:

Объе́кт в программировании — некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеющая заданные значения свойств (атрибутов) и операций над ними (методов)

Так то да, и 5 это объект, и фукнция `+' это объект.

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

ну так чо тебе мешает этот y ставить первым в своем выражении? Было g(x, y) стало y g(x).

Ладно, а что делать для такого случая?

class C a where
  h :: [a] -> Int

instance C Int where
  h = length

instance C Double where
  h x = length x + 1

-- Tests
> h [1, 2, 3]
3
> h [1.0, 2.0, 3.0]
4
> h (tail [1])
0
> h (tail [1.0])
1
?

То есть для списка целых — одна функция, для списка вещественных — другая.

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

Мне проще на других типах показать, думаю, суть от этого не изменится

List do(
  length := getSlot("size")
)


NumberList := List clone do(
   push := method(x, if(x type == "Number", resend))
)
StringList := List clone do(
   push := method(x, if(x type == "Sequence", resend))
   length := method(resend - 1)
)

stringList := StringList clone
numberList := NumberList clone

stringList push(1) 
stringList push("foo")
stringList push("bar")

numberList push("foo")
numberList push(1)
numberList push(2)


numberList println // list(1, 2)
stringList println // list(foo, bar)

numberList length println // 2
stringList length println // 1

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

Кто-то запрещает возвращать из метода новый объект, не трогая старый

Если метод уже что-то возвращает, то некуда новый объект возвращать. Ну и стилю мышления ООП как-то плохо соответствует: newPoint = point move x y, newDisplay = display draw newPoint — так, что ли? А что должно произойти при newDisplay = display draw point1; newDisplay2 = display draw point1 ? На дисплее должна быть только вторая точка?

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

Привет. На лиспер не заходишь? Поможешь с вопросом по cl-gobject-introspection?

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

то некуда новый объект возвращать.

Что значит некуда?

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

Мне проще на других типах показать, думаю, суть от этого не изменится

Только чтобы с твоими numberList, stringList необходимо использовать именно твои конструкторы. Предположим, была функция getCoords display, возвращающая list(x,y) с целыми координатами.

В Хаскеле автоматически результат получает возможность применения операции h. То есть можно делать h(getCoords display).

У тебя придётся либо переписывать функцию getCoords, либо для добавления метода использовать явную конвертацию : display getCoords toNumberList h

А потом модель дисплея изменилась и координаты стали вещественные. В Хаскеле опять всё автоматически применится, а у тебя придётся всюду изменять getCoords toNumberList на getCoords toDoubleList

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

Я спросил исключительно по приведённой формулировке. А ты пока подумай ещё раз насчёт посещения психиатра.

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

Ага, если бы ты еще понял эту формулировку, было бы ваще хорошо.

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

Функция «+» — это не символ «+». Символ это одно, а то куда он указывает(будучи ссылкой) — это другое. Так вот, речь идет не о сиволе «+», который есть имя сообщения, и может указывать, к слову, на что угодно, хоть на функцию «devide», а именно о том объекте, куда он указывает, в данном случае — функции.

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

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

Оппа, мамкин программист пожаловал

оппа, с каких пор маня-говнокодеры против мамкиных программистов?

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

Вообще, когда говорят «возвращает», обычно имеется в виду — ложит на стек, не

Это в Forth. А в ООП нет понятия «стек». Есть только объекты и их сообщения. И глобального объекта «стек» в ООП без мутабельных объектов тоже быть не может.

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

Хз, можно ли в ООП, по крайней мере в синхронном коде забыть о стеке. К примеру, есть разница между fu = function(){return 1}иfu = function(){myStack.push(1)}, никуда от этого не денешься. Стек омжно в ООП рассматривать как дефолтный объект для хранения промежуточных результатов, так правильнее будет. Совсем абстрагироваться от него мы не можем.

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

без мутабельных объектов тоже быть не может.

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

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

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

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

newPoint = point move x y, newDisplay = display draw newPoint — так, что ли? А что должно произойти при newDisplay = display draw point1; newDisplay2 = display draw point1 ? На дисплее должна быть только вторая точка?

firstPoint = new Point(10, 20)
secondPoint = new Point(30, 40)

firstPoint.display
secondPoint.display
somequest
() автор топика
Ответ на: комментарий от monk

В Хаскеле автоматически результат получает возможность применения операции h. То есть можно делать h(getCoords display).

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

coords1 = getCoords // returned instance of DoubleList
coords2 = getCoords // returned instance of NumberList

coords1 h
coords2 h
А можно и наподобие твоего синтаксиса сделать, так, чтобы h обрабатывала входные данные в зависимосити о их типа. Вариантов очень много, какой лучше выбрать — зависит от конкретного кейза. Вот в этом одно из преимуществ: ООП не ограничивает в выборе вариантов решений.

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

Там выше по треду утверждалось, что объект это

сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеющая заданные значения свойств (атрибутов) и операций над ними (методов)

И было сообщено, что «+» (математическая функция) - это объект.

В следующий раз урок чтения будет платным.

leave ★★★★★
()

Object-oriented design is the roman numerals of computing.

И ты это высказыване своим постом ещё раз подтвердил. ¯\_(ツ)_/¯

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

что «+» (математическая функция)

«+» в ООП — это не математическая функция, а сообщение, во-первых, во-вторых, тот объект функции, который возвращается в ответ на это сообщение, тоже не является математической функцией, а является реализацией этой функции. Ты достал уже своей хренью, успокойся уже, мне тупых анонимусов хватает, а тут ты еще под ногами болтаешься со своими детскими представлениями о программировании. Иди уже, какой нибудь кед поставь себе новый плазменный на десктоп, больше толка будет.

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

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

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

Нет, зачем. 5 +(1) — ты тут посылаешь объекту 5 сообщение +(1) и возвращаешь объект 6. Посылка сообщения не означает обязательно мутацию реципиента.

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

Но объект — это ведь что-то имеющее состояние. Какое состояние у объекта 5 и как он может его поменять?

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

Какое состояние у «объекта» +

то в котором он пребывает по-дефолту. Ты его можешь изменить. Состояние объекта — это поведение объекта, которое можно изменить, в ФП, by contrast, состояние менять нельзя, поэтому *считается*, что его нет.

Кроме того, при вызове, он проходит ряд состояний — подстановка, редукция, возврат значения.

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

Блин, это же элементарно

5 do(
  setSlot("+", getSlot("-"))
)

writeln(5 +(1)) // 4

Поменял, как ты считаешь?

как он может его поменять?

В быдло-ООП не может.

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

Изменение состояния означает изменение поведения. Так, в примере выше, объект 5 стал отвечать на сообщение + иным образом. Хотя в Ъ понятие «изменение состояния» — это хреновое описания происходящего. Уместнее говоить об изменении поведения. К примеру, акторы вообще не имеют четко определенного состояния. Но так уж сложилось, говорим не птичьем языке, поэтому пусть будет состояние.

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

Честно признаться я не понимаю, что ты пытаешься доказать. ;)

Есть фунции — они детерминированные. (Например Date() и Rnd() функциями не являются, т.к. возвращают каждый раз другое значение.)

Есть объекты — нечто с внутренним состоянием. (Структуры, классы, процессы в erlang.)

И есть методы/сообщения — нечто меняющее (или не меняющее) у объекта его внутренне состояние.

Так о чём мы сейчас говорим?

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

что ты пытаешься доказать

Я ничего не пытался доказать, просто отвечал на вопросы

(Например Date() и Rnd() функциями не являются, т.к. возвращают каждый раз другое значение.)

Они являются функциями, просто с точки зрения ФП они не чистые. Но тут все сводится к терминологии — функция как подпрограмма, функция как отображение, функция как объект — это все разные понятия. ИМХО, в программировании математических функций вообще не может быть, это просто член в голове. Функция может описывать программу, но не реализовывать ее.

И есть методы/сообщения — нечто меняющее у объекта его внутренне состояние.

Не обязательно.

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

нечто меняющее (или не меняющее) у объекта его внутренне состояние.

В смысле, менять сообщение ничего не обязано, хотя в ответ на сообщение объект может изменить свое состояние, если захочет.

Так о чём мы сейчас говорим?

О том, видимо, что все что ты перечислил — это все объекты(или акторы), включая сообщения.

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

это все объекты

«Если у тебя в руках молоток, то всё кажется гвоздем» ;)

В 90% случаем что-то одно можно выразить через что-то другое. С потерей или выиграшем — вопрос другой. Считай, что это изоморфизмы.

Но в общем случае, на ООП свет клином не сошёлся.

beastie ★★★★★
()
Ответ на: комментарий от somequest
firstPoint.display
secondPoint.display

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

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

coords1 = getCoords // returned instance of DoubleList
coords2 = getCoords // returned instance of NumberList

Так я и говорю, что если ты на какой-то тип добавляешь метод, то тебе придётся переписывать всё, что потенциально может вернуть этот тип.

То есть раньше у тебя была системная библиотека с кодом

Display := Object clone do(
   ...
   getCoords := method(list(Display height, Display width))
)

Теперь ты добавил h для NumberList. Идёшь в системную библиотеку и исправляешь на

Display := Object clone do(
   ...
   getCoords := method(NumberList(Display height, Display width))
)

Потом библиотека обновляется и heigth и width становятся вещественными

Снова лезешь в код:

Display := Object clone do(
   ...
   getCoords := method(DoubleList(Display height, Display width))
)

А можно и наподобие твоего синтаксиса сделать, так, чтобы h обрабатывала входные данные в зависимосити о их типа.

Вот это можно продемонстрировать?

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

И куда эти точки должны выводится?

Да куда угодно, метод display, конечно вызывает где то мутации, но мы бы могли бы написать и так

new Point(10, 20).display
new Point(30, 40).display
эти объекты были бы созданы, произвели бы где то побочные эффекты и сразу уничожены GC, поэтому явного сосояния у нас тут нет, так же как и в монадах. Изначальный Point просто возвращает свой экземпляр, а сам остается нетронутым, я к этому.

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

придётся переписывать всё, что потенциально может вернуть этот тип.

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

Вот это можно продемонстрировать?

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

h := method(x,
  if((x type) == "Foo", doSmth...; return)
  if((x type) == "Bar", doSmthElse...; return)
)

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

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

Так можно и ООП считать разновидностью процедурного программирования. Ведь любой метод можно реализовать ветвлением.

можно создать сабкласс, и переопределить в нем только нужное

И сабкласс придётся создавать на все используемые объекты с результатом нужного типа. В принципе, реализуемо, но неуклюже.

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