11/08/2018, 21:11

Road to ruby silver (Part 3)

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

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

Part1
Part2

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"
0