Edited at

Road to ruby silver (Part 3)

More than 1 year has passed since last update.

This is just some note for who want to get Ruby Silver certification. :)

Part 1

Part 2


Chapter 4: Object orientation


4.1. Define a class


4.1.1. Syntax

class <<ClassName>>

end

Sample:

class Foo

def initialize a = 0
@a = a
end

def method1
@a
end
end

foo1 = Foo.new(1)
foo1.method1 ⇛ 1
foo2 = Foo.new
foo2.method1 ⇛ 0

★ All commands is not contained in any method will be ran when class is loaded

puts 1

class Hoge
puts 2
end
puts 3


1
2
3


4.1.2. Instance method and initialization method

class Foo

def initialize a = 0
@a = a
end

def method1
@a
end
end

⇛ method1 is an instance method of class Foo

foo1 = Foo.new
foo1.class == Foo ⇛ true


4.1.3. Inheritance class (クラス継承)

class FooExt < Foo

def initialize a, b
@b = b
super a
end

def method2
@a + @b
end
end

fooExt = FooExt.new(3, 4)
fooExt.method1 ⇛ 3
fooExt.method2 ⇛ 7

FooExt.superclass ⇛ Foo


4.1.4. super

For calling the nearest parent class


4.2. Instance method


4.2.1. Class object (クラスオブジェクト)


  • Create new instance of class Foo

instance1 = Foo.new(1)

instance2 = Foo.new(1)

instance1.object_id ⇛ 70323462947500
instance2.object_id ⇛ 70323462930480
Foo.object_id ⇛ 70323462538720


4.2.2. What method will be called?

class Foo

def initialize a
@a = a
end

def get_a
@a
end
end

class FooExt
def initialize a, b
super a
@b = b
end

def get_a
puts "FooExt get_a: #{@a}"
end

def get_b
puts "FooExt get_b: #{@b}"
end
end

foo = Foo.new 3
foo.get_a
⇛ 3
foo.get_b
⇛ NameError
foo_ext = FooExt.new 3, 4
foo_ext.get_a
⇛ "FooExt get_a: 3"
foo_ext.get_b
⇛ 4


4.2.3. Inheritance chain and method_missing


  • For above example:

FooExt => Foo => Object => Kernel => BasicObject


  • Get all ancestors of a class

Foo.ancestors

⇛ [Foo, Object, Kernel, BasicObject]
FooExt.ancestors
⇛ [FooExt, Foo, Object, Kernel, BasicObject]


  • Check a class is interiting an other class

Foo < BasicObject

⇛ true
Foo < FooExt
⇛ false



  • instance_methods and instance_variables

Foo.instance_methods(false)

⇛ [:method1]
FooExt.instance_methods(false)
⇛ [:method2]
Foo.instance_variables
⇛ []
FooExt.instance_variables
⇛ []
foo1.instance_variables
⇛ [:@a]
fooExt.instance_variables
⇛ [:@b, :@a]


  • alias

alias new_method_name old_method_name

alias new_global_var_name old_global_var_name


  • undef

undef method_name

undef method1_name, method2_name

Sample:

class Test

def method1; end

def method2; end

alias :method3 :method2
undef :method2
end

Test.instance_methods(false)
⇛ [:method1, :method3]

class Test2
def method1; end

def method2; end

alias :method3 :method2
undef :method3
end

Test2.instance_methods(false)
⇛ [:method1, :method2]


  • Override method_missing method

class Test

def method_missing m, *args
puts "called: Test##{m}"
super
end
end

Test.new.do_not_existed_method
⇛ called: Test#do_not_existed_method
NoMethodError: undefined method `do_not_existed_method' for #<Test:0x007feaea84dc08>


4.2.4. Open class


  • All classes in Ruby are open. This means you can define new method for any other class.

class Test

def method1
"method1"
end
end

Test.object_id
⇛ 70119510391780

t1 = Test.new
t1.method1
⇛ "method1"
t1.method2
⇛ NameError

class Test
def method2
"method2"
end
end

Test.object_id
⇛ 70119510391780

t2 = Test.new
t2.method1
⇛ "method1"
t2.method2
⇛ "method2"
t1.method2
⇛ "method2"

★ Attention: There is attention when you reopen a class that is extending an other class.

class A; end

class B; end
class C < B
end


class C < A
end
⇛ TypeError

class C < B
end
⇛ OK

class C
end
⇛ OK


4.3. Mix-in (Modules)


4.3.1. Module definition and include


  • Some attentions about module:


    • Can not create instance for module

    • Can not inherit

    • Can be included in class or other module



module A; end

A.new ⇛ NoMethodError

module B < A
end
⇛ SyntaxError


  • Module definition syntax

module <<module_name>>

def method_name
end
end


  • Module is not inheritable
    ⇛ Ancestor of it contains only it.

module TestModule

def method1
"method1"
end
end

TestModule.ancestors
⇛ [TestModule]

TestModule.instance_methods
⇛ [:method1]


  • Include module to a class

class B

include TestModule
end

b = B.new
b.method1
⇛ "method1"
B.instance_methods(false)
⇛ [] # :method1 is not defined inside of B ⇛ do not appear in here


  • Check all modules a class is including

module A; end

module B; end

class Test1
include A
end

class Test2 < Test1
include B
end

Test1.included_modules
⇛ [A, Kernel]
Test2.included_modules
⇛ [A, B, Kernel]


4.3.2. Load flow when include module

module TestModule

def method1
"TestModule#method1"
end
end

class A
include TestModule

def method1
"A#method1"
end
end

class B
def method1
"B#method1"
end

include TestModule
end

A.new.method1 ⇛ "A#method1"
B.new.method1 ⇛ "B#method1"


4.4. Singleton class


4.4.1. Class method


  • Definition

class A; end

def A.class_method_1
"class_method_1"
end

A.class_method_1
⇛ "class_method_1"

A.new.class_method_1
⇛ NoMethodError


  • Define method for only 1 instance

class Foo; end

foo1 = Foo.new
foo2 = Foo.new

foo1.object_id ⇛ 70175903036120
foo1.class ⇛ Foo

def foo1.method_1
"method_1"
end

foo1.object_id ⇛ 70175903036120
foo1.class ⇛ Foo
foo1.class.instance_methods ⇛ []

foo1.method_1
⇛ "method_1"
foo2.method_1
⇛ NoMethodError

When define method for only instance foo1,

system will create an singleton class like:

class #foo1 < Foo

def method_1
end
end

and foo1 is setted as the instance of class #foo1


4.4.2. Singleton class


  • Definition sample


class Foo; end

foo1 = Foo.new
singleton_class = class << foo1
self
end

singleton_class
⇛ #<Class:#<Foo:0x007ff2fd810c48>>


class Foo; end

foo2 = Foo.new
class << foo2
def method1
"method1"
end
end

foo2.method1 ⇛ "method1"


  • Define new method inside an other method

class A

def method1
def method2
end
end
end

A.instance_methods ⇛ [:method1]
A.new.method1
A.instance_methods ⇛ [:method1, :method2]


4.4.3. extend


  • Sample of using mix-in in singleton class

module TestModule

def method1; "method1"; end
end
class Foo; end
foo1 = Foo.new
class << foo1
include TestModule
end

foo1.method1 ⇛ "method1"


  • Use extend

module TestModule

def method1; "method1"; end
end

class Foo; end
foo1 = Foo.new
foo1.extend(TestModule)
foo1.method1 ⇛ "method1"