Ненормальное
объектно-ориентированное
программирование
ForkConf 2013, 3 марта
z, ? | toggle help (this) |
space, → | next slide |
shift-space, ← | previous slide |
d | toggle debug mode |
## <ret> | go to slide # |
c, t | table of contents (vi) |
f | toggle footer |
r | reload slides |
n | toggle notes |
p | run preshow |
P | toggle pause |
ForkConf 2013, 3 марта
фанат языков программирования
Посылка сообщения vs вызов метода
Классы как объекты
Прототипное ООП
Mixins и Traits
class A(object):
def __init__(self, value):
self.__var = value
a = A(10)
a._A__var = 5
print a._A__var # => 5
class A
attr_reader :var # getter
def initialize(value)
@var = value
end
end
a = A.new(10)
a.instance_exec do
@var = 5
end
puts(a.var) # => 5
C# -- вызов метода, в Ruby -- посылка сообщения
object.foo(bar)
Обыкновенные данные
'foo', [arg1, arg2, ...]
Пример приближённый к реальной практике
class AuthSession
def connect_via_gplus(email)
# ...
end
def method_missing(name, args)
case name.to_s
when /connect_via_(.+)/
# загрузить нужный код
else
super # обычное поведение
end
end
end
Например можно динамически
s = AuthSession.new
# предопределённый метод
s.connect_via_gplus('foo@bar.ru')
# хитрая обработка сообщения
s.connect_via_vk('foo@bar.ru')
# NoMethodError
s.method_that_doesnt_match()
Теперь все хитрые вещи выражаются более унифицированно
class API
def register(klass1, klass2)
# здесь можно сделать
# какую-нибудь хитрую
# композицию из
# нескольких классов
@generator =
compose(klass1, klass2)
end
def generate_unit()
@generator.new
end
end
class API
def register_generator(klass)
@generator = Class.new(klass) do
def foobar
# some specific
end
end
end
def generate_unit()
@generator.new
end
end
в некоторых языках также упрощаются следующие вещи
provider = 'gplus'
s = AuthSession.new
# вызов метода, это вызов метода!
method = 'connect_via_' + provider
s.send(method, 'foo@bar.com')
fields_names = DataBase::Table
.find('objects').fields()
class Model
for name in fields_names
define_method(name) do
@record.get_attribute[name]
end
end
end
JavaScript создавали когда прототипное ООП входило в моду
матрицы -- векторы, классы -- объекты
module Comparable
def sort
# ...
end
end
class A
include Comparable
end
class B
include Comparable
end
each
)all?
, any?
, chunk
, collect
, collect_concat
, count
, cycle
, detect
, drop
, drop_while
, each_cons
, each_entry
, each_slice
, each_with_index
, each_with_object
, entries
, find
, find_all
, find_index
, first
, flat_map
, grep
, group_by
, include?
, inject
, lazy
, map
, member?
, none?
, one?
, partition
, reduce
, reject
, reverse_each
, select
, slice_before
, take
, take_while
, to_a
, zip
можно контроллировать приоритет определений методов, включать динамически
module FirstMixin
def foo; 'first'; end
end
module SecondMixin
def foo; 'second'; end
end
class A
include FirstMixin
include SecondMixin
end
trait Comparable
require :compare
def sort
# ...
end
end
class A
include Comparable
end
trait FirstTrait
def foo; 'first'; end
end
trait SecondTrait
def foo; 'second'; end
end
class A
include FirstTrait
include SecondTrait,
rename_to: {foo: 'second_foo'}
end