Skip to content

Instantly share code, notes, and snippets.

@vasiliy-pdk
Created January 17, 2020 14:36
Show Gist options
  • Save vasiliy-pdk/0cc8864280e5fade68fe2ca2c14c4b03 to your computer and use it in GitHub Desktop.
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
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