Програмистите са следващите господари на света.
Какво прави alias
?
class Something
def name() 'baba' end
alias relative name
def name() 'dyado' end
end
p Something.new.relative
Прави копие на метода
Каква е разликата между alias
и alias_method
?
alias_method
е метод, докато alias
е синтаксис
class Something
1.upto(5).each do |index|
alias_method "to_s_#{index}", :to_s
end
end
Кой (и как) може да вика private
методи?
class Something
private
def foo
end
end
self.foo
)Какви са конвенциите за имена на методи, променливи, константи и имена на класове?
UpperCamelCase
- константи (включва имена на класове)normal_snake_case
- променливи, методиSCREAMING_SNAKE_CASE
- константи, които не са имена на класове или модулиНа какво могат да завършват методите в Ruby?
?
, ако са предикати!
, ако имат две версии=
, ако са setter-и%
Наследяването в Ruby става така:
class Person
def name() 'The Doctor' end
end
class PolitePerson < Person
def introduction
"Hi, I am #{name}"
end
end
PolitePerson.new.introduction # "Hi, I am The Doctor"
Object
Object
(с изключение на родителя на Object
...)Имате достъп до private
методите:
class Person
private
def name() 'The Doctor' end
end
class PolitePerson < Person
def introduction() "Hi, I am #{name}" end
end
PolitePerson.new.introduction # "Hi, I am The Doctor"
class Base; end
class SpaceStation < Base; end
base = Base.new
station = SpaceStation.new
base.is_a? Base # true
station.is_a? SpaceStation # true
station.is_a? Base # true
base.instance_of? Base # true
station.instance_of? SpaceStation # true
station.instance_of? Base # false
#is_a?
има синоним #kind_of?
class Base; end
class SpaceStation < Base; end
base = Base.new
station = SpaceStation.new
base.kind_of? Base # true
station.kind_of? SpaceStation # true
station.kind_of? Base # true
#is_a?
по принцип.
#instance_of?
само когато искате да не бъде наследник.
Може да предефинирате метод и да извикате версията на родителя със super
.
class Person
def introduction_to(other)
"Hello #{other}."
end
end
class PolitePerson < Person
def introduction_to(other)
super("Mr. #{other}") + " How do you do?"
end
end
queen = PolitePerson.new
queen.introduction_to('Smith') # "Hello Mr. Smith. How do you do?"
Ако извикате super
без скоби родителският метод получава същите аргументи.
class Person
def introduction_to(other)
"Hello #{other}."
end
end
class PolitePerson < Person
def introduction_to(other)
super + " How do you do?"
end
end
queen = PolitePerson.new
queen.introduction_to('Smith') # "Hello Smith. How do you do?"
super
и super()
са различни:
class Person
def introduction_to(other)
"Hello #{other}."
end
end
class PolitePerson < Person
def introduction_to(other)
super() + " How do you do?"
end
end
queen = PolitePerson.new
queen.introduction_to('Smith') # error: ArgumentError
include
-нати
ancestor chain
module Foo; end
module Bar; end
module Qux; end
class Base
include Foo
end
class Derived < Base
include Bar
include Qux
end
Derived.ancestors # [Derived, Qux, Bar, Base, Foo, Object, Kernel, BasicObject]
module Foo; end
module Bar; end
module Qux
include Foo
include Bar
end
class Thing
include Qux
end
Thing.ancestors # [Thing, Qux, Bar, Foo, Object, Kernel, BasicObject]
Има само една версия на метода:
module Talking
def greeting() "Hello, #{name}" end
end
class Base
include Talking
def name() 'Base' end
def say_hi_base() greeting end
end
class Derived < Base
include Talking
def name() 'Derived' end
def say_hi_derived() greeting end
end
derived = Derived.new
derived.say_hi_base # "Hello, Derived"
derived.say_hi_derived # "Hello, Derived"
Интересен gem:
MethodFinder.find('abc', 'ABC')
%w[a b c].find_method { |a| a.unknown(1) ; a == %w[a c] }
"Всичко наследява от Object
"
Object
не наследява от Object
BasicObject
BasicObject
е nil
BasicObject
е минималистичен клас, подходящ за прокситаKernel
е миксиран в Object
Kernel
(#puts
, #eval
и т.н.)
Object
(#inspect
, #tap
, #methods
и т.н.)
Object
Само обекти от същия клас могат да викат protected методи
class Vector
def initialize(x, y) @x, @y = x, y end
def inspect() "Vector.new(#@x, #@y)" end
def +(other)
Vector.new(*coords.zip(other.coords).map { |a, b| a + b })
end
protected
def coords() [@x, @y] end
end
vector = Vector.new(1, 2) + Vector.new(3, 4)
vector # Vector.new(4, 6)
vector.coords # error: NoMethodError
private
се ползва постоянно
protected
почти никога
protected
, защото могат да се викат със self.
отпред
public
. Не го ползваме, а просто слагаме публичните методи отгоре
Module
и Class
Понеже private
и protected
са методи:
class Person
def name() end
def age() end
private :name, :age
end
Или дори:
class String
private :upcase!, :downcase!
end
"Foo".upcase! # error: NoMethodError
Помните ли, че дефиницията на метод връща името на метод като символ?
def foo() end # :foo
Значи може да направите така:
class Person
private def name
"My name is a secret."
end
private def age
"I'm feeling feminine, so my age is a secret, too."
end
end
Класовете и модулите могат да служат като именувани пространства.
module Useless
class Thing
end
end
class Grandfather
class StraightRazor
end
end
Useless::Thing.new # #<Useless::Thing:0x41aa9d44>
Grandfather::StraightRazor.new # #<Grandfather::StraightRazor:0x41aa9b14>
Ако се намирате в модул, няма нужда да ползвате пълния път до константите:
module Useless
class Thing
end
Thing.new # #<Useless::Thing:0x41f65220>
end
Useless::Thing.new # #<Useless::Thing:0x41f64ff0>
Thing.new # error: NameError
def
, module
и class
@foo
)bacon = 2
def foo
chunky = 10
1.times do
chunky # 10
chunky = 44
end
chunky # 44
bacon # error: NameError
end
foo()
module
и class
ви местят из дървото на константите
::
отпред (::Foo
)
Object
PLACE = 'root'
module Outer
PLACE = 'intermediate'
module Inner
PLACE = 'deep'
end
end
PLACE # "root"
Outer::Inner::PLACE # "deep"
module Outer
module Inner
PLACE # "deep"
::PLACE # "root"
end
PLACE # "intermediate"
Inner::PLACE # "deep"
end
Може да дефинирате класови методи така:
class Something
def Something.answer
42
end
end
Something.answer # 42
Не може да ги викате неквалифицирано от инстанцията:
class Something
def Something.answer
42
end
def do_stuff
answer # error: NameError
Something.answer # 42
end
end
thing = Something.new
thing.answer # error: NoMethodError
Something.answer # 42
thing.do_stuff
Достъпни са в наследниците:
class Base
def Base.answer() 42 end
end
class Derived < Base
def Derived.say_answer
answer # 42
Base.answer # 42
end
end
Derived.answer # 42
Base.answer # 42
Derived.say_answer
Има и други начини за дефиниция на класови методи: