Edited at

Road to Ruby Silver (Part 4)

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

Part 3


Chapter 4: Object orientation (continue)


4.5. Class Method


4.5.1. Class Class

① Example about using class method

class Foo; end

foo_class = Foo.class
→ Class

② Create an instance of class Class

2.1.

Foo = Class.new

Foo.new.class
→ Foo

2.2.
FooExt = Class.new(Foo) do # → Foo is super class
def initialize b # → Init method of FooExt class
super()
@b = b
end

def method_2 c # → Instance method method_2
@b + c
end
end


4.5.2. Define a class method

class Class

def new_method
puts "This method will be applied as a class method of any class"
end
end

class Foo; end
Foo.new_method
→ This method will be applied as a class method of any class
String.new_method
→ This method will be applied as a class method of any class

class Foo

def Foo.new_method
puts "This is Foo.new_method"
end
end

Foo.new_method
→ This is Foo.new_method

class Foo

def self.new_method
puts "New method of Foo"
end
end

Foo.new_method
→ "New method of Foo"

class Foo

class << self
def new_method
puts "new_method"
end
end
end

Foo.new_method
→ "new_method"


4.5.3. include and extend

2.3.0 :005 >   class C4

2.3.0 :006?> include M4
2.3.0 :007?> extend M4
2.3.0 :008?> end
=> C4
2.3.0 :009 > C4.method1
=> 1
2.3.0 :010 > C4.new.method1
=> 1


4.6. Scope of methods, attributes


Definition


  • public: can called in every where → this is default

  • protected: can called only inside object, instance of sub class

  • private: can called only inside object

class Bar1

def public_method1; 1; end
public
def public_method2; 2; end

protected
def protected_method1; 1; end
def protected_method2; 2; end

private
def private_method1; 1; end
end

Bar1.new.public_method1 → 1
Bar1.new.public_method2 → 2
Bar1.new.protected_method1 → NoMethodError
Bar1.new.protected_method2 → NoMethodError
Bar1.new.private_method1 → NoMethodError


  • We can change the scope of method or attributes by using key word: public, private, protected like below:

class Bar1

def public_method1; 1; end
public
def public_method2; 2; end

protected
def protected_method1; 1; end
def protected_method2; 2; end

private
def private_method1; 1; end
end

class Bar2 < Bar1
public :private_method1
end

Bar2.new.private_method1 → 1

★ NOTE: Can not use self for calling a private method inside object

class Bar2

def public_method1
private_method1
end

def public_method2
self.private_method1
end

private
def private_method1; 1; end
end

b = Bar2.new
b.public_method1 → 1
b.public_method2 → NoMethodError: private method `private_method1' called for #<Bar2:0x007fc3ca806a70>


4.6.2. Kernel module and function



  • Object class is including Kernel module

2.3.0 :052 > Object.included_modules

=> [Kernel]


  • In Kernel, there are some methods are defined, sample: p, puts. You can check all methods of Kernel module by run: Kernel.methods

  • Almost methods of Kernel module are private, so we can not call them with self

puts "a" → this is ok

self.puts "a" → NoMethodError

NOTE: When you defined a method inside irb, that method will be a method of Object class.

This means all other classes (what are an instance of Object) can use this method.

2.3.0 :056 > self

=> main
2.3.0 :057 > def my_func; 1; end
=> :my_func
2.3.0 :058 > Integer.my_func
=> 1
2.3.0 :059 > String.my_func
=> 1
2.3.0 :060 > "a".my_func
=> 1


4.7. Variables and Constants


4.7.1. Local variables and global variables


  • Local variables

2.3.0 :061 > v1 = 1

=> 1
2.3.0 :062 > class Bar
2.3.0 :063?> p v1
2.3.0 :064?> end
NameError: undefined local variable or method `v1' for Bar:Class

→ In above sample, we can not define class Bar because when defining it, we call variable v1.

v1 is defined in main but it can not be used inside other scope.

Other sample:

v1 = 1

class Bar2
v2 = 2
def method1; v1; end
def method2; v2; end
end
b = Bar2.new
b.method1 → NoMethodError: undefined local variable or method `v1' for #<Bar2:0x007fc3ca1ea268>
b.method2 → NoMethodError: undefined local variable or method `v2' for #<Bar2:0x007fc3ca1ea268>


  • Global variables: add $ as the first character when define variable name

$v1 = 1

class Bar2
$v2 = 2
def method1; $v1; end
def method2; $v2; end
end
b = Bar2.new
b.method1 → 1
b.method2 → 2


4.7.2. Instance variable


  • Use prefix @ when define variable name

  • Default is nil when variable is not initialized

@v1 = 1

class Bar
@v2 = 2
def method1; @v1; end
def method2; @v2; end
end
b = Bar.new
b.method1 → nil
b.method2 → nil

class Bar2
def initialize; @v3 = 3; end

def method3; @v3; end
end
Bar2.new.method3 → 3


  • Auto generate getter, setter methods for instance variable by using attr_reader, attr_writer, attr_accessor, attr

Keyword
Meaning

attr_reader
Generate only setter method

attr_writer
Generate only getter method

attr_accessor
Generate both setter and getter

attr
Generate only getter

class B

attr :var

def initialize
@var = 2
end
end

b = B.new
b.var = 2
b.var


4.7.3. Class variables


  • Use prefix @@ when define variable name

  • Raise error when called uninitizalized variable

class Bar

@@v1 = 1
def v1; @@v1; end
def v2; @@v2; end
end
b = Bar.new
b.v1 → 1
b.v2 → NameError

class Bar2 < Bar
def new_v1; @@v1; end
end
b2 = Bar2.new
b2.new_v1 → 1


4.7.4. Nested scope of constants


  • In previous part, we investigated about Constant.

A = 1

p A → 1
A = 2 → warning
p A → 2


  • Constant can be not defined inside method

def func

B = 1
end
→ SyntaxError: dynamic constant assignment


  • Nested scope of constants


    • Normaly



module B; end

B::A = 1 → Ok
B::A::A = 1 → TypeError


  • Modulized

module M

A = 1
class B
A = 2
end
class C
end
end

M::A → 1
M::B::A → 2
M.constants
→ [:A, :B, :C]
M::B.constants
→ [:A]


  • const_missing

module M

def self.const_missing(id)
id
end
end

M::UNEXISTED_CONSTANT
→ :UNEXISTED_CONSTANT