This is just some note for who want to get Ruby Silver certification. :)
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 includingKernel
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 ofKernel
module by run:Kernel.methods
- Almost methods of
Kernel
module are private, so we can not call them withself
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 usingattr_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