-
Notifications
You must be signed in to change notification settings - Fork 2
/
about_class_methods.rb
178 lines (142 loc) · 4.37 KB
/
about_class_methods.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
require File.expand_path(File.dirname(__FILE__) + '/neo')
class AboutClassMethods < Neo::Koan
class Dog
end
def test_objects_are_objects
fido = Dog.new
assert_equal true, fido.is_a?(Object)
end
def test_classes_are_classes
assert_equal true, Dog.is_a?(Class)
end
def test_classes_are_objects_too
assert_equal true, Dog.is_a?(Object)
end
def test_objects_have_methods
fido = Dog.new
assert fido.methods.size > 55
end
def test_classes_have_methods
assert Dog.methods.size > 100
end
def test_you_can_define_methods_on_individual_objects
fido = Dog.new
def fido.wag
:fidos_wag
end
assert_equal :fidos_wag, fido.wag
end
def test_other_objects_are_not_affected_by_these_singleton_methods
fido = Dog.new
rover = Dog.new
def fido.wag
:fidos_wag
end
assert_raise(NoMethodError) do
rover.wag
end
end
# ------------------------------------------------------------------
class Dog2
def wag
:instance_level_wag
end
end
def Dog2.wag
:class_level_wag
end
def test_since_classes_are_objects_you_can_define_singleton_methods_on_them_too
assert_equal :class_level_wag, Dog2.wag
end
def test_class_methods_are_independent_of_instance_methods
fido = Dog2.new
assert_equal :instance_level_wag, fido.wag
assert_equal :class_level_wag, Dog2.wag
end
# ------------------------------------------------------------------
class Dog
attr_accessor :name
end
def Dog.name
@name
end
def test_classes_and_instances_do_not_share_instance_variables
fido = Dog.new
fido.name = "Fido"
assert_equal "Fido", fido.name
assert_equal nil, Dog.name
end
# ------------------------------------------------------------------
class Dog
def Dog.a_class_method
:dogs_class_method
end
end
def test_you_can_define_class_methods_inside_the_class
assert_equal :dogs_class_method, Dog.a_class_method
end
# ------------------------------------------------------------------
LastExpressionInClassStatement = class Dog
21
end
# Not only does every method in Ruby return a value (and not just
# a Class) but every line executed has a return value.
def test_class_statements_return_the_value_of_their_last_expression
assert_equal 21, LastExpressionInClassStatement
end
# ------------------------------------------------------------------
SelfInsideOfClassStatement = class Dog
self
end
def test_self_while_inside_class_is_class_object_not_instance
assert_equal true, Dog == SelfInsideOfClassStatement
end
# ------------------------------------------------------------------
class Dog
# you can write class method the same way using "self." in place
# of the class name.
def self.class_method2
:another_way_to_write_class_methods
end
end
def test_you_can_use_self_instead_of_an_explicit_reference_to_dog
assert_equal :another_way_to_write_class_methods, Dog.class_method2
end
# ------------------------------------------------------------------
class Dog
class << self
def another_class_method
:still_another_way
end
end
end
def test_heres_still_another_way_to_write_class_methods
assert_equal :still_another_way, Dog.another_class_method
end
# THINK ABOUT IT:
#
# The two major ways to write class methods are:
# class Demo
# def self.method
# end
#
# class << self
# def class_methods
# end
# end
# end
#
# Which do you prefer and why?
# Are there times you might prefer one over the other?
# Personally, I prefer the first. It's really weird for me to have to
# write another class definition like that. While I guess it could
# make sense the former is clearer to me. I like to define my class
# methods separately from my instance ones which also helps make that
# difference clear so I'm not concerned about def statements looking
# the same. I just don't find the latter very clear initially.
# ------------------------------------------------------------------
def test_heres_an_easy_way_to_call_class_methods_from_instance_methods
fido = Dog.new
assert_equal :still_another_way, fido.class.another_class_method
end
end