Където аз задавам въпроси!
Какво ще направи следният код?
things = [:bacon, :cheese, :tea]
p things[1]
p things[10]
things[4] = :snickers
p things
Ще отпечата :cheеse
, nil
и
[:bacon, :cheеse, :tea, nil, :snickers]
.
Кое е подходящо за ключ в хеш?
immutable обекти, които могат да се хешират.
Какво ще изведе следният код:
words = %w[foo bar baz]
names = words
names[0] << 'l'
names[1] = 'qux'
words[2] = 'larodi'
puts words
%w[fool qux larodi]
Какви са методите, които завършват на ?
или !
#foo?
е предикат, #foo!
е по-деструктивна версия на #foo
Каква е разликата между Proc
и lambda
? Каква им е връзката с yield
?
Дълго :)
Дефинират се с class
. Методите, дефинирани в тялото на класа,
стават методи на инстанциите му. Инстанцират се се с ИмеНаКласа.new
.
class Bacon
def chunky?
'yes, of course!'
end
end
bacon = Bacon.new
bacon.chunky? # "yes, of course!"
Полетата (още: instance variables) имат представка @
.
class Vector
def initialize(x, y)
@x = x
@y = y
end
def length
(@x * @x + @y * @y) ** 0.5
end
end
vector = Vector.new 2.0, 3.0
vector.length() # 3.605551275463989
vector.length # 3.605551275463989
По подразбиране имат стойност nil
.
class Person
def heh
@something
end
end
person = Person.new
person.heh # nil
В метод на може да извикате друг със self.име_на_метод
или просто име_на_метод
:
class Person
def initialize(name) @name = name end
def say_hi() puts "My name is #{@name}!" end
def sound_smart() puts "1101000 1101001" end
def talk
self.say_hi
sound_smart
end
end
mel = Person.new 'Mel'
mel.talk
Такова подравняване на методи е гадно, но пък се събира в слайд
В методите на класа, self
е референция към обекта,
на който е извикан методът. Като this
в Java.
class Person
def me
self
end
end
person = Person.new
person # #<Person:0x9678000>
person.me # #<Person:0x9678000>
person.me.me # #<Person:0x9678000>
Полетата не са публично достъпни. Може да ги достигнете само чрез метод.
class Person
def initialize(age)
@age = age
end
def age
@age
end
def set_age(age)
@age = age
end
end
person = Person.new(33)
person.age # 33
person.set_age 20
person.age # 20
Разбира се, set_age
е гадно име на метод. Може и по-добре:
class Person
def age
@age
end
def age=(value)
@age = value
end
end
person = Person.new
person.age = 33 # Същото като person.age=(33)
person.age # 33
Последното е досадно за писане. Затова:
class Person
attr_accessor :age
end
person = Person.new
person.age = 33
person.age # 33
Ако ви трябва само getter или setter, може така:
class Person
attr_reader :name
attr_writer :grade
attr_accessor :age, :height
end
attr_accessor
е метод, който генерира два метода — #foo
и #foo=
. Достъпен е в дефинициите на класове. Неформален термин за такива
методи е "class macro".
Има ги в изобилие.
Обърнете внимание, че следните два реда правят едно и също:
person.age()
person.age
Няма разлика между достъпване на атрибут и извикване на метод, който го изчислява. Това се нарича Uniform Access Principle и като цяло е хубаво нещо.
В Ruby важат следните конвенции.
UpperCamelCase
plain_snake_case
Във всеки момент може да "отворите" клас и да му добавите методи.
class Person
def name
'River'
end
end
class Person
def say_hi
"Hi, I am #{name}."
end
end
Person.new.say_hi # "Hi, I am River."
Person.new.name # "River"
Ако дефинирате един метод два пъти, втората дефиниция измества първата.
class Something
def name
'Tom Baker'
end
def name
'Colin Baker'
end
end
Something.new.name # => 'Colin Baker'
Въпреки името си, alias
прави копие на метод.
class Array
alias old_inject inject
def inject(*args, &block)
puts "I see you are using #inject. Let me help!"
old_inject(*args, &block) * 0.01
end
end
[1, 2, 3, 4, 5, 6].inject { |a, b| a + b } # 0.21
Ако викнете #methods
на нещо, ще получите масив от символи
с имената на методите му.
Помните ли Array#-
?
class Person
def foo() end
def bar() end
end
Person.new.methods - Object.new.methods # [:foo, :bar]
Много интуитивно.
class Vector
attr_accessor :x, :y
def initialize(x, y)
@x, @y = x, y
end
def +(other)
Vector.new(x + other.x, y + other.y)
end
def inspect
"Vector.new(#@x, #@y)"
end
end
Vector.new(1, 5) + Vector.new(3, 10) # Vector.new(4, 15)
class Person
def say_hi
"Hello! I am #{name}"
end
private
def name
'the Doctor'
end
end
person = Person.new
person.say_hi # "Hello! I am the Doctor"
person.name # error: NoMethodError
Ако един метод е private
, не може да го викате с явен получател.
Дори със self.
class Person
def say_hi
"Hello! I am #{self.name}"
end
private
def name
'the Doctor'
end
end
person = Person.new
person.say_hi # error: NoMethodError