LINUX.ORG.RU

Вот я твой язык не понимаю. Почему ты вместо слова «класс» употребляешь «тип»? У типов какая-то особая форма наследования?

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

У нас не только ООП, у нас ещё есть такой монстр как CL.

В принципе да - даже в CL всё так, но я всё равно какой-то подвох чувствую в этой пёстрой терминологии.

ados ★★★★★
()
Последнее исправление: ados (всего исправлений: 1)
Ответ на: комментарий от no-such-file

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

К слову, в любом нормальном ООП-языке это тривиально делается.

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

То что хочет ТС насколько я понял — тупо связать один и тот же метод с разными классами. А у тебя конкретный метод связан с одним классом.

В CL есть эффективный метод (как по PCL) который получается после работы комбинатора и методы из которых он комбинируется.

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

То что хочет ТС насколько я понял — тупо связать один и тот же метод с разными классами

Тогда было бы (or type1 type2) что эквивалентно просто объявлению двух отдельных методов для type1 и type2, да. Какая-то сомнительная затея, т.к. такой метод должен работать с объектом через один и тот же интерфейс, тогда его можно определить просто на этом интерфейсе.

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

что эквивалентно просто объявлению двух отдельных методов для type1 и type2, да

Нет, я имел в виду один и тот же метод, связанный с разными классами.

vikingfilmtracker
()
Ответ на: комментарий от no-such-file

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

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

Нет, я имел в виду один и тот же метод, связанный с разными классами

Можно и один и тот же. Просто в этом нет смысла в принципе - нужно делать интерфейс и на нём метод определять.

no-such-file ★★★★★
()
Ответ на: комментарий от vikingfilmtracker

К слову, в любом нормальном ООП-языке это тривиально делается.

Э-э-э, если под «нормальными» ты понимаешь мейнстримные, то в них это тоже не делается никак, кроме способов предложенных ИТТ.

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

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

pseudo-cat ★★★
() автор топика

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

type: o2
type: h20
type: c

type area1(derive: 02 h20 c)
type area2(derive: 02)
type area3(derive: h20)
...

method is-alive? ((area-object : O2)):
    print "it isn't alive, because only o2 exists!"

method is-alive? ((area-object : h2O)):
    print "it isn't alive, because only h20 exists!"

method is-alive? ((area-object : (02 && h20 && c))):
    print "it's alive, all components here!"

[b]А не делать так - [/b]
method is-alive? ((area-object : area1)):
    print "it's alive, because its Area1 where, as I know, all components exists!"

method is-alive? ((area-object : t)):
    print "it isn't alive, because as I know, only Area1 contains all components. If the new Area with all components will here - write duplicate method for this!"

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

Можно создать подтип, реализующий два интерфейса. Затем определить один метод для этого подтипа

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

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

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

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

Унаследоваться от обоих, добавить в метод ещё один параметр, передавать твой объект как два разных параметра - не пойдёт?

(defmethod f ((x первый-интерфейс) (y второй-интерфейс)))

(f x x)

den73 ★★★★★
()
Ответ на: комментарий от pseudo-cat

Не, так не получится. Кроме того

method is-alive? ((area-object : O2)):
    print "it isn't alive, because only o2 exists!"
Почему должно не сработать на area1? Тогда уж
method is-alive? ((area-object : O2 && !h20 && !c)):
    print "it isn't alive, because only o2 exists!"

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от Gentooshnik

примеры как это сделать на всех этих языках. Не срача ради, действительно интересно

Чё там интересного? Просто засовываем функцию в класс динамически. Всё.

no-such-file ★★★★★
()
Ответ на: комментарий от pseudo-cat

На Io это даже проще можно сделать

O2 := Object clone
H20 := Object clone
C := Object clone

Area1 := Object clone do( appendProto(O2); appendProto(H20); appendProto(C))
Area2 := Object clone do(appendProto(H20))
Area3 := Object clone do(appendProto(C))

isAlive := method(
   l := list()
   list(O2, H20, C) foreach(t, self hasProto(t) and l push(t type) ) 
   phrase := l join(", ") 
   if(
    l size == 3,
    writeln( "is alive because " .. phrase .. " all exists."),
    writeln("is not alive because " .. phrase .. " only exists.")
   )
)

list(Area1, Area2, Area3) foreach(area,
   area setSlot("isAlive", getSlot("isAlive"))
)
removeSlot("isAlive")

Area1 isAlive    #>>>>is alive because O2, H20, C all exists.
Area2 isAlive    #>>>>is not alive because H20 only exists.
Area3 isAlive    #>>>>is not alive because C only exists.

И, не требуется для этого даже общего метода

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

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

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

Проверкой предков это можно сделать даже в Java. Насколько я понял, ТС надо, чтобы не просто логика, а именно диспетчеризация происходила на основании наличия обоих интерфейсов.

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

В жаве это в общем случае не сделаешь, если предки меняются в рантайме.

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

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

vikingfilmtracker
()
Ответ на: комментарий от no-such-file

так более специфичный метод же выбирается и, если не вызывать call-next-method, то дальше цепочка вызовов не пойдет, разве нет?

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от vikingfilmtracker

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

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от vikingfilmtracker

И в CL для этого не требуется общий метод.

(defclass O2 () ())
(defclass H2O () ())
(defclass C () ())

(defclass Area1 (O2 H2O C) ())
(defclass Area2 (H2O) ())
(defclass Area3 (C) ())

(defun alive? (area)
  (let ((l (list)))
    (dolist (e '(O2 H2O C))
      (when (typep area (find-class e))
	(push e l)))
    (if (= (length l) 3)
      (format t "is alive because ~{~A~^, ~} all exist~%" l)
      (format t "is not alive because only ~{~A~^, ~} exist~%" l))))

(alive? (make-instance 'area1))
(alive? (make-instance 'area2))
(alive? (make-instance 'area3))

Это буквальный перевод. Вывод аналогичный.

Только, насколько я понял, ТС совсем не это нужно. И вообще, тема не про языкосрач, а про решение конкретной задачи в конкретном языке. Я поэтому и просил код в gist, а не сюда.

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

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

Area1 isAlive    #>>>>is alive because O2, H20, C all exists.
Area2 isAlive    #>>>>is not alive because H20 only exists.
Area3 isAlive    #>>>>is not alive because C only exists.

Area2 do( appendProto(O2); appendProto(C) )
Area1 removeProto(O2)

Area1 isAlive    #>>>>is not alive because H19, C only exists.
Area2 isAlive    #>>>>is alive because O1, H20, C all exists.
Area3 isAlive    #>>>>is not alive because C only exists.
                 
Так твой код работает?

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

аналогичный

он же хотел его как defmethod объявить, а не как обычную функцию?

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

Почему ты вместо слова «класс» употребляешь «тип»?

Потому что в CL есть классы и есть типы, в джаве `int` и `float` тоже типы а не классы.

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

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

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

А, ну это все игра слов. Суть не в отличии класса от типа, а в отличии примитивов от непримитивов.

где объектная система не единственный способ построения архитектуры.

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

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

Иными словами, примитивные типы — это те же самые типы, только кастрированные(не первоклассные)

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

Когда любая сущность является суть одним и тем же — это всегда мощней

Оно не является одним и тем же, ты можешь проверять значение на соответствие любому типу, объектному или нет, но от обычных типов наследоваться не можешь и тд.

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

Оно не является одним и тем же

Эта фраза относилась к случаю, когда все типы первоклассны.

Да, короче говоря, примитивные типы — это типы у которых не реализовано поведение нормальных типов, чей интерфейс является ограниченным или ортогональным семантике языка.

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

ортогональным семантике языка

Общелисп это объектный язык или функциональный или процедурный?

это типы у которых не реализовано поведение нормальных типов

У них полностью реализовано поведение типов, классы это отдельный подкласс типов.

http://sellout.github.io/media/CL-type-hierarchy.png

Бирюзовое - обектная система, а все вместе - система типов.

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

что в CL есть классы и есть типы, в джаве `int` и `float` тоже типы а не классы.

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

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

чтобы любая сущность была консистентным типом, ведь сама объектная система CL — это надстройка над CL

Где тут противоречие?

Сам CL вообще не имеет ООП-интерфейса

Где проходит грань между CL и MOP?

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