LINUX.ORG.RU

Как в зависимоти от объекта выполнить некоторые действия?

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

Книжки по образцово-грамотному ООП (особенно по языкам, которые стояли у Истоков) в один голос твердят, что негоже принимать решения, основываясь на типе объекта, лучше уж попросить объект сделать что-то, а он там решит, что делать (в зависимости от своего типа, да!).

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

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

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

Пистон при вызове несуществующего метода кидает исключение. Сам объект, в отличии от того что в Smalltalk или Ruby, ничего не получит.

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

несуществующего

Я про несуществующие ещё ничего не говорил :) Я намекал на визитор какбе

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

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

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

Вообще-то это ближе к жабке и плюсам. В рубях и смолтоках-то как раз дернуть объект на его класс проще простого.

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

Тут выбор - костыльный паттерн-матчинг на isinstance'ах или дабл диспатч в стиле визитора. Выбор из них исключительно вопрос вкуса.

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

Почти.

Я нутром чую, что

if (class-of(foo) == Foo) && class-of(bar) == Bar) then pewpewew()

- говно, но обосновать это с (прости Г-ди) академической точки зрения пока не могу. Придёт время, и, !

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

Тут выбор - костыльный паттерн-матчинг на isinstance'ах или дабл диспатч в стиле визитора. Выбор из низ исключительно вопрос вкуса.

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

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

Я нутром чую, что

if (class-of(foo) == Foo) && class-of(bar) == Bar) then pewpewew()

А я нутром чую, что ты выдумал не относящуюся к делу куету.

tailgunner ★★★★★ ()

QSqlRecord

судя по букве Q, это Qt?

CAction

судя по букве C, это... WTF o_O ?!

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

красивее было бы список пар держать: [(actn0, rec0), (act1, rec1), ...]

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

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

Я нутром чую, что
if (class-of(foo) == Foo) && class-of(bar) == Bar) then pewpewew()
- говно

аналог этого кода на питоне будет:

if (type(foo) is Foo) and (type(bar) is Bar):

и такой код действительно считается плохим.

‘isinstance’ сработает даже если Foo будет одним из классов в цепочке наследования класса объекта ‘foo’. И, собственно, в отличие от использования type не по делу, isinstance для того и придуман.

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

Суть не в этом. Суть в том, что решения принимаются на основе принадлежности объекта к определенному классу (иерархии)

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

Суть в том, что решения принимаются на основе принадлежности объекта к определенному классу (иерархии)

И это плохо, потому что... ?

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

Похоже, ты просто привык к другому приготовлению ООП.

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

У него там QAction и QSqlRecord, какие у них могут быть общие операции? Он скорее всего ошибся уже на этапе занесения их в единый список

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

поведение описано не через взаимодействие объектов.

Как уже сказали, isinstance в моем пример не используется для описания поведения. Мммкей, попробуем по-другому: перепиши пример так, чтобы не использовать isinstance.

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

Для проверки, что список состоит из пар правильного типа.

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

Абсолютно идиоматические решения для рубей и прочих смолтоков

В Ruby и Smalltalk можно просто к обоим классам добавить нужный метод. А использование Visitor'а в данном случае ничем не будет отличаться от isinstance, разве что этот isinstance будет спрятан в кишках Visitor'а (и, возможно, присыпан сахарком).

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

Для меня подмешивание ассоциируется с миксинами и трейтами, а это немножко не то. Я имею в виду, что можно взять существующий класс, добавить к нему новый метод, и все ранее созданные объекты этого класса автоматически получат эти методы. А в Ruby с помощью refinements можно ещё и контролировать область видимости этих методов.

module MyRefinements
  refine CAction do
    def foo
      # ...
    end
  end

  refine QSqlRecord do
    def foo
      # ...
    end
  end
end

module MyCode
  using MyRefinements

  # ...
  actions_and_records.each(&:foo)
end
theNamelessOne ★★★★★ ()
Ответ на: комментарий от theNamelessOne

Вообще офигеть.

>>> class A():
...     pass
... 
>>> b = A()
>>> b.c()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: A instance has no attribute 'c'
>>> A.c = (lambda this: 100)
>>> b.c()
100
aedeph_ ★★ ()
Ответ на: комментарий от aedeph_

Круто, но мы вроде бы говорили про Ruby и Smalltalk (хотя про то, что Python так может, я не знал).

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

И это плохо, потому что... ?

Потому что, айыыы. Потому же, почему и динамик_каст в крестах часто антипаттерн, как звоночек о косяках в архитектуре.

Если честно,я не могу внятно сформулировать, почему. Но придёт время, и я это обязательно сделаю, если не превращуюсь к кулинхао

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

Потому что в таком случае метод взаимодействующий с объектами каких-то классов описан не в этом классе. Нарушение инкапсуляции, не работает полиморфизм.

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

метод взаимодействующий с объектами каких-то классов описан не в этом классе

Я до сих пор удивляюсь - где вы там увидели взаимодействие? Там проверяется контракт, не более. У вас какой-то коленный рефлекс на isinstance.

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

Принадлежность к классу не может быть контрактом

Может и является.

это нарушение инкапсуляции.

Нет.

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

И это плохо, потому что... ?

Например. У тебя есть класс A, у него некий признак a. Есть у него наследний B, который тоже обладает признаком a. Ты решил сделать проверку наличия признака a через isinstance A. А потом у класса B появляется наследник C, которому надо этот признак убрать (ну вот такой частный случай, ага). В обычном ООП ты бы изначально использовал метод hasMark(a) и переопределил его где надо. А здесь как поступишь?

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

Ты решил сделать проверку наличия признака a через isinstance A

Зачем я так сделал?

В обычном ООП ты бы изначально использовал метод hasMark(a). А здесь как поступишь?

Если задача в том, чтобы проверить наличие атрибута «a», она решается hasattr. Если задача в чем-то другом - сформулируй ее.

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

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

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

потом у класса B появляется наследник C, которому надо этот признак убрать

В стандартную библиотеку батареек питона кстати такое не принимают.

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

В стандартную библиотеку могут принимать или не принимать что угодно, но по факту такие ситуации бывают. Я не так давно писал код, гда у класса метод возвращает true, а у некоторых его детей false. И вполне возможно, что у кого-то из детей их детей в будущем может переопределяться обратно в true.

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