Created
January 17, 2020 14:36
-
-
Save vasiliy-pdk/0cc8864280e5fade68fe2ca2c14c4b03 to your computer and use it in GitHub Desktop.
An exercise for understanding methods visibility in Ruby, created for one of Tech Lunches
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class A | |
def access_bar | |
puts "#{self} accessing bar. Bar is #{bar}" | |
end | |
def access_foo(fooer) | |
print "#{self} sends `foo` message which is " | |
puts fooer.foo | |
end | |
private | |
def bar | |
"private in #{self}" | |
end | |
def foo | |
"private in #{self}" | |
end | |
end | |
class B < A | |
def bar | |
"public in #{self}" | |
end | |
protected | |
def foo | |
"protected in #{self}" | |
end | |
end | |
class C < A | |
def foo | |
"public in #{self}" | |
end | |
private | |
def bar | |
"olololo private in #{self}" | |
end | |
end | |
class D < A | |
end | |
class E < A | |
def access_bar | |
puts "#{self} accessing bar. Bar is #{bar}" | |
end | |
end | |
class G | |
protected | |
def foo | |
"protected in #{self}" | |
end | |
end | |
a1 = A.new | |
b1 = B.new | |
c1 = C.new | |
d1 = D.new | |
e1 = E.new | |
g1 = G.new | |
class Person | |
def compare(another_person) | |
age <=> another_person.age | |
end | |
protected | |
def age | |
42 | |
end | |
end | |
# What happens next? ruby whats_wrong_with_visibility.rb | |
# Note: there are some notes and conclusions - scroll right | |
a1.access_bar # | |
b1.access_bar # | |
c1.access_bar # | |
d1.access_bar # | |
e1.access_bar # | |
a1.access_foo c1 # | |
# a1.access_foo b1 # protected method `foo' called for #<B:0x0000000000cd93a8> (NoMethodError) | |
# a1.access_foo a1 # private method `foo' called for #<A:0x0000000002581860> (NoMethodError) | |
b1.access_foo b1 | |
b1.access_foo B.new # | |
c1.access_foo c1 # | |
# c1.access_foo b1 # `access_foo': protected method `foo' called for #<B:0x00000000015c93f0> (NoMethodError) | |
# c1.access_foo a1 # private method `foo' called for #<A:0x0000000001070a20> (NoMethodError) | |
# a1.access_foo g1 # | |
# Conclusion: Initially I thought that we have to define method as protected in order to be able to override it in a child class. That was wrong. And I was not alone in it. | |
# Instead we can use private method. `protected` should be used for the case when we want to allow another instance of the same class call the method | |
# you can call a protected method on an object x , as long as | |
# the default object (self) is an instance of the same class as x or of an ancestor or | |
# descendant class of x ’s class. | |
class SelfWithPrivate | |
def access_bar_via_self | |
puts "#{self} accessing bar from within string interpolation. Bar is #{self.bar}" | |
end | |
def populate_foo | |
self.foo = 'Ololol!' | |
end | |
private | |
def bar | |
"I am a private bar" | |
end | |
def foo=(value) | |
puts 'Calling private setter method foo = ' + value | |
end | |
end | |
s = SelfWithPrivate.new | |
# s.access_bar_via_self # private method `bar' called for #<A:0x0000000000fd46e8> (NoMethodError) | |
s.populate_foo # | |
# s.foo = '43' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment