Наследяването в 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
Имате достъп до 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
Kernel
е миксиран в Object
Kernel
(#puts
, #eval
и т.н.)
Object
(#inspect
, #tap
, #methods
и т.н.)
BasicObject
е минималистичен клас, подходящ за проксита
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
веднъж.
protected
, защото могат да се викат с self.
отпред.
public
. Не го ползваме, а просто слагаме публичните методи отгоре.
Module
и Class
.
Класовете и модулите могат да служат като именовани пространства.
module Useless
class Thing
end
end
class Grandfather
class StraightRazor
end
end
Useless::Thing.new # #<Useless::Thing:0x9fc48fc>
Grandfather::StraightRazor.new # #<Grandfather::StraightRazor:0x9fc4744>
Ако се намирате в модул, няма нужда да квалицирате константите:
module Useless
class Thing
end
Thing.new # #<Useless::Thing:0x90950ac>
end
Useless::Thing.new # #<Useless::Thing:0x909ef6c>
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
)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