This is just some note for who want to get Ruby Silver certification. :)
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
andinstance_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"