2. Object Oriented Programming
Класс (class) – абстрактное описание реального объекта или
математической модели, содержит набор полей (свойств /
атрибутов) и методов.
Объекты – конкретное представление абстракции, экземпляры
класса. Каждый объект имеет свой личный id! Пример: Студент –
класс (абстракция), Астапенко Борис Вячеславович с номером
зачетки 6221328 – объект.
Методы – это функции, принадлежащая классу или объекту.
Состоят из некоторого количества операторов для выполнения
какого-то действия, могут иметь набор входных аргументов и
возвращаемое значение.
Поля (attributes) – переменные, принадлежащие либо
непосредственно самому классу, либо экземплярам класса
(instance).
Instance-переменные (или просто переменные) создаются по
одной копии для каждого конкретного объекта (экземпляра
класса).
3. Класс (class) – абстрактное описание реального объекта или математической модели, содержит набор
атрибутов и методов.
class Unicorn
def self.health # class method
90
end
def self.speed
return 7 # optional
end
end
Unicorn.health # => 90
4. Объект (object/instance) – конкретное представление абстракции.
class Unicorn
@@population = 0 # @@class_variable
def initialize(hp) # constructor
@health = hp # @instance variable
@@population += 1
end
def self.population
@@population
end
end
james = Unicorn.new(26)
alex = Unicorn.new(90)
Unicorn.population # => 2
5. Be very careful with class variables! *
Class variables belong to class hierarchies don’t
classes itself.
@@v is defined in the context of main, it belongs
to main’s class Object... and to all the descendants
of Object.
MyClass inherits from Object, so it ends up
sharing the same class variable!
@@v = 1
class MyClass
@@v = 2
end
@@v # => 2
MyClass.ancestors # => [MyClass, Object, Kernel, BasicObject]
self # => main
self.class # => Object
6. class Unicorn
def initialize(hp)
@health = hp
end
def health # getter method
@health
end
def health=(hp) # setter method
@health = hp
end
end
james = Unicorn.new(90)
james.health # => 90
james.health = 25
james.health # => 25
Getters, setters…
9. Getters, setters… Accessors!
attr_reader :isbn
_____________
def isbn
@isbn
end
attr_writer :isbn
_____________
def isbn=(isbn)
@isbn = isbn
end
attr_accessor :isbn
_____________
def isbn
@isbn
end
def isbn=(isbn)
@isbn = isbn
end
10. class Unicorn
attr_reader :surname, :name
attr_accessor :health
attr_writer :private_message
…
end
james = Unicorn.new(…)
james.surname # => “Lebron”
james.health = 25
james.health # => 25
james.private_message = “secret”
Getters, setters… Accessors!
The ruby way.
12. Механизм ООП, объединяющий вместе код и данные, которыми он манипулирует,
исключая вмешательство извне. Доступ к данным осуществляется только через
публичный интерфейс.
Инкапсуляция
13. Если бы все данные в программе имели бы глобальную область видимости, то пришлось
бы для всех данных и для каждого метода использовать уникальное название (а оно
должно быть информативным!), постоянно бы приходилось следить, чтобы новые имена
не пересекались уже с использованными. Про перегрузку операций можно было бы
забыть.
Инкапсуляция позволяет скрыть данные и функции, используемые исключительно
членами класса или его потомками. Это упрощает описание класса для его
использования внешними функциями и повышает надежность его работы т.к. важные
данные защищены от несанкционированного доступа.
“Хороший тон” – скрытие всех данных, используемых классом, и обеспечение доступа к
ним только посредством соответствующих методов. Это устраняет все вопросы с
областью видимости переменных, позволяет использовать в каждом классе простые и
информативные имена методов и переменных, не заботясь о том, что подобные уже
могут использоваться в других классах.
Инкапсуляция
14. Спецификаторы доступа
PUBLIC
Можно вызывать только внутри
других методов данного объекта
Доступен из любого места в коде.
Присваивается по умолчанию
PROTECTED PRIVATE
Можно вызывать только внутри
других методов данного объекта
или его родственников
15. class User
attr_reader :name
def initialize(name, protected_info)
@name, @protected_info = name, protected_info
end
def info_of(user)
user.protected_info
end
def get_id
my_private_id
end
protected
def protected_info
@protected_info
end
private
def my_private_id
self.object_id
end
end
james = User.new('James', 'JMS13')
john = User.new('John', 'JN1')
puts james.name # => James
puts james.info_of(john) # => JN1
puts james.get_id # => 70110475881600
puts james.my_private_id # ERROR
17. Механизм языка, позволяющий описать новый класс на основе уже существующего
(родительского, базового) класса. Класс-потомок может добавить собственные методы и
свойства (не будут доступны родителю), а также пользоваться родительскими методами
и свойствами.
Наследование
18. class Unicorn
attr_accessor :health
end
class WarUnicorn < Unicorn
def blind(victim)
victim.skip_action
end
end
grisha = WarUnicorn.new
valera = Minotaur.new
grisha.blind(valera)
Наследование
19. Classes
super
class Parent
def say(word)
puts “Hi from parent. Say #{word}"
end
end
class Child < Parent
def say(word)
super
puts “Hi from child. Say #{word}”
end
end
Child.new.say “wat”
# => “Hi from parent. Say wat”
# => “Hi from child. Say wat”
When you invoke super with no arguments Ruby
sends a message to the parent of the current object,
asking it to invoke a method of the same name as the
method invoking super.
It automatically forwards the arguments that were
passed to the method from which it's called.
Called with an empty argument list - super()-it sends
no arguments to the higher-up method, even
if arguments were passed to the current method.
Called with specific arguments - super(a, b, c) - it
sends exactly those arguments.
20. Classes
again about initialize
class Parent
def initialize
puts “Parent init”
end
end
class NoInitChild < Parent; end
NoInitChild.new #=> “Parent init”
class NormalChild < Parent
def initialize
puts “NormalChild init”
end
end
NormalChild.new #=> "NormalChild init”
class SuperChild < Parent
def initialize
puts “SuperChild”
super
puts “init”
end
end
SuperChild.new
#=> SuperChild
#=> Parent init
#=> init
Parent's initialize runs automagically only if child has
none. Else, parent's must be called (through super)to
run.
21. Modules & Method lookup
When you include a module in a
class (or even in another module)
Ruby creates an anonymous class
that wraps the module and inserts
the anonymous class (proxy class)
in the chain, just above the
including class itself.
Module M
def my_method
‘M#my_method'
end
end
class C
include M
end
class D < C; end
D.new.my_method
#=> “M#my_method”
22. Наследуясь, в классе — потомке (дочернем классе или подклассе или субклассе или …)
вы можете переопределять унаследованные свойства и методы.
Другим объектам при взаимодействии не важно какого класса объект(родитель или
наследник) с которым они имеют взаимодействие. Важно, что он имеет тот интерфейс,
который от него ожидают.
Полиморфизм
class Elf
def attack
fire
end
end
class GrandElf < Elf
def attack
fire_twice
end
end
24. Duck Typing
“If it walks like a duck and quacks like a duck, then it must be a duck ”
25. Duck Typing
“If it respond_to? :quack, then it must be a duck”
class Duck
def quack
‘Quack!’
end
end
class FakeDuck
def quack
‘Muuu. Oh shi… :|’
end
end
def make_it_quack(duck)
duck.quack
end
puts make_it_quack(Duck.new) #=> “Quack!”
puts make_it_quack(FakeDuck.new) #=> “Muuu. Oh shi… :|”
You don’t care that an object is an instance of class Duck.
You just care that it responds to quack(), whether they’re regular
methods, Singleton Methods, or even Ghost Methods.
ООП (OOP) – парадигма программирования, в которой основными концепциями являются понятия объектов и классов.
PROTECTED и PRIVATE – вспомогательные методы.
Private-методы можно вызывать только на неявном получателе (implicit receiver)
Global scope: entire program.
Global scope: entire program.
Global scope: entire program.
Global scope: entire program.
Global scope: entire program.
Global scope: entire program.
Global scope: entire program.
Global scope: entire program.
10 пункт говорит о том, что где бы ни создавались @instance_variables, они всегда будут переменными текущего объекта, т.е. объекта, на который в данный момент ссылается self!
В 11 пункте идёт речь о том, что если метод вызван без явного получателя, то это значит, что подразумевается вызов метода в контексте текущего объекта (self).
10 пункт говорит о том, что где бы ни создавались @instance_variables, они всегда будут переменными текущего объекта, т.е. объекта, на который в данный момент ссылается self!
В 11 пункте идёт речь о том, что если метод вызван без явного получателя, то это значит, что подразумевается вызов метода в контексте текущего объекта (self).
Неявная типизация или утиная типизация (англ. Duck typing) — вид динамической типизации, применяемой в некоторых языках программирования (D, Perl, Smalltalk, Python, Objective-C, Ruby, JavaScript, TypeScript, Groovy, ColdFusion, Boo, Lua, Go), которая позволяет полиморфно работать с объектами, которые не связаны в иерархии наследования, но имеют необходимый набор методов. То есть считается, что объект реализует интерфейс, если он содержит все методы этого интерфейса, независимо от связей в иерархии наследования и принадлежности к какому-либо конкретному классу.
In Ruby, we rely less on the type (or class) of an object and more on its capabilities. Hence, Duck Typing means an object type is defined by what it can do, not by what it is. Duck Typing refers to the tendency of Ruby to be less concerned with the class of an object and more concerned with what methods can be called on it and what operations can be performed on it. In Ruby, we would use respond_to? or might simply pass an object to a method and know that an exception will be raised if it is used inappropriately.