- Сообщений: 3147
- Спасибо получено: 2651
Удобная работа с With
11 года 8 мес. назад - 11 года 8 мес. назад #73485
от DeadElf79
DeadElf79 создал тему: Удобная работа с With
Этот метод мне сильно понравился еще в будни использования VisualBasic, а позднее - и в Delphi. Сегодня я хочу показать его и вам.
Как это работает?
Допустим, у вас есть какой-нибудь объект, содержащий несколько методов, которые вам нужно вызывать последовательно, чтобы добиться нужного результата. Чаще всего это можно заметить в отрисовке в различных меню и вот как оно выглядит:
Что вы можете сделать, чтобы не переписывать один и тот же кусок текста (self.contents)?
Так выглядит код во втором случае:
Неправда ли, куда проще?
Описание with
Так выглядит сам метод with, который добавляется прямо в Kernel:
Он получает переменную и выполняет в ее контексте указанные в блоке действия, после чего возвращает саму переменную. В качестве переменной также может быть вызов конструктора какого-либо класса. Пример:
У этого метода есть только одно строгое правило - переменная (точнее - передаваемый объект) должен быть указан в скобках перед блоком.
Более сложный пример для самых навороченных (или ленивых?):
В данном случае мы видим пример того, что в отрисовке можно при желании можно в такой же блок метода with вписать помимо self.contents еще и font. Как-то так:
Оригинал кода взят из ответа на данный вопрос: #with(object) &block trick (StackOverflow.com)
Как это работает?
Допустим, у вас есть какой-нибудь объект, содержащий несколько методов, которые вам нужно вызывать последовательно, чтобы добиться нужного результата. Чаще всего это можно заметить в отрисовке в различных меню и вот как оно выглядит:
Code:
def refresh
self.contents.clear
self.contents.font.color=system_color
self.contents.font.bold=true
self.contents.draw_text(0,0,width-32,32,'Some Text')
end
Что вы можете сделать, чтобы не переписывать один и тот же кусок текста (self.contents)?
- Скопировать и вставлять с помощью Ctrl+C и Ctrl+V
- Использовать With
Так выглядит код во втором случае:
Code:
def refresh
with (self.contents) {
clear
font.color=system_color
font.bold=true
draw_text(0,0,width-32,32,'Some Text')
}
end
Неправда ли, куда проще?
Описание with
Так выглядит сам метод with, который добавляется прямо в Kernel:
Code:
def with(instance, &block)
instance.instance_eval(&block)
instance
end
Он получает переменную и выполняет в ее контексте указанные в блоке действия, после чего возвращает саму переменную. В качестве переменной также может быть вызов конструктора какого-либо класса. Пример:
Code:
def with(instance, &block)
instance.instance_eval(&block)
instance
end
class Abc
def some
'some'
end
def somedo
'moar some'
end
end
name=Abc.new
puts name.class
with (name) {
puts some
puts somedo
}
new_name=with (Abc.new) { puts some }
puts new_name.class
У этого метода есть только одно строгое правило - переменная (точнее - передаваемый объект) должен быть указан в скобках перед блоком.
Более сложный пример для самых навороченных (или ленивых?):
Code:
def with(instance, &block)
instance.instance_eval(&block)
instance
end
class Abc
attr_reader :defg
def initialize
@defg=Defg.new
end
def some
'some'
end
def somedo
'moar some'
end
class Defg
def moar_work
'i\'m feelin\' lucky!'
end
end
end
name=Abc.new
with (name) {
with(defg) {
puts moar_work
}
}
В данном случае мы видим пример того, что в отрисовке можно при желании можно в такой же блок метода with вписать помимо self.contents еще и font. Как-то так:
Code:
def refresh
with (self.contents) {
clear
with(font) {
color=system_color
bold=true
}
draw_text(0,0,width-32,32,'Some Text')
}
end
Оригинал кода взят из ответа на данный вопрос: #with(object) &block trick (StackOverflow.com)
Последнее редактирование: 11 года 8 мес. назад пользователем DeadElf79.
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
11 года 8 мес. назад #73486
от DeadElf79
DeadElf79 ответил в теме Удобная работа с With
Обнаружил небольшую ошибку во втором (расширенном) примере, по причине возникновения которой не рекомендую все же использовать несколько with один в другом.
Лучше использовать:
Оригинала реализации clear у меня нет, поэтому я предполагаю, что в этом методе так же сбрасываются все изменения шрифта так как переопределение шрифта перед перерисовкой текста сбрасывает сделанные изменения.
Также, обнаружилось дополнительное правило, вполне логичное, но незамеченное мною изначально:
Все выполняется в контексте указанного объекта. Соответственно, использовать метод system_color из класса Window_Base, содержащего Bitmap (в contents) уже нельзя. Если придумаю как можно красиво обойти это - дополню тему.
Code:
def refresh
with (self.contents) {
clear
with(font) {
color=system_color
bold=true
} # по окончании блока изменения могут никак не отразиться на шрифте
draw_text(0,0,width-32,32,'Some Text')
}
end
Лучше использовать:
Code:
def refresh
with (self.contents) {
clear
font.color=Color.new(255,0,0)
font.bold=true
draw_text(0,0,width-32,32,'Some Text')
}
end
Оригинала реализации clear у меня нет, поэтому я предполагаю, что в этом методе так же сбрасываются все изменения шрифта так как переопределение шрифта перед перерисовкой текста сбрасывает сделанные изменения.
Также, обнаружилось дополнительное правило, вполне логичное, но незамеченное мною изначально:
Все выполняется в контексте указанного объекта. Соответственно, использовать метод system_color из класса Window_Base, содержащего Bitmap (в contents) уже нельзя. Если придумаю как можно красиво обойти это - дополню тему.
Спасибо сказали: strelokhalfer
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
- strelokhalfer
-
- Не в сети
- Живу я здесь
-
- Знатный грамотей
Скрыть
Больше
- Сообщений: 1640
- Спасибо получено: 1080
11 года 2 мес. назад #78773
от strelokhalfer
"Стрелок, что-то ты неочень похож на свой аватар..."(с)
strelokhalfer ответил в теме Удобная работа с With
Перенес в Факультет, думаю, там оно нужнее.
"Стрелок, что-то ты неочень похож на свой аватар..."(с)
Пожалуйста Войти или Регистрация, чтобы присоединиться к беседе.
Время создания страницы: 0.098 секунд
