In ruby, you can do this:
class Thing
public
def f1
puts "f1"
end
private
def f2
puts "f2"
end
public
def f3
puts "f3"
end
private
def f4
puts "f4"
end
end
where now f1 and f3 and public, f2 and f4 is private. What is going on internally that allows you to invoke a class method that then changes the method definition? How can I implement the same functionality (ostensibly to create my own java like annotations)
for example...
class Thing
fun
def f1
puts "hey"
end
notfun
def f2
puts "hey"
end
end
and fun and notfun would change the following function definitions.
Thanks
To make it simple: public, private and protected methods are just that. Methods. You use them to perform certain functions on your code. The difference between the three comes from who and/or what has access to them. Why do we use them?
Public members (generally methods declared in a class) are accessible from outside the class. The object of the same class is required to invoke a public method. This arrangement of private instance variables and public methods ensures the principle of data encapsulation.
Protected methods are a balance between public and private methods. They are similar to private methods in that they cannot be accessed in the public scope. Neither the client nor the program can...
Python - Public, Protected, Private Members Classical object-oriented languages, such as C++ and Java, control the access to class resources by public, private, and protected keywords. Private members of the class are denied access from the environment outside the class.
You can sometimes shove Ruby into an espressso cup. Let's see how.
Here's a module FunNotFun...
module FunNotFun
def fun
@method_type = 'fun'
end
def notfun
@method_type = 'not fun'
end
def method_added(id)
return unless @method_type
return if @bypass_method_added_hook
orig_method = instance_method(id)
@bypass_method_added_hook = true
method_type = @method_type
define_method(id) do |*args|
orig_method.bind(self).call(*args).tap do
puts "That was #{method_type}"
end
end
@bypass_method_added_hook = false
end
end
... that you can use to extend a class ...
class Thing
extend FunNotFun
fun
def f1
puts "hey"
end
notfun
def f2
puts "hey"
end
end
... with this result:
Thing.new.f1
# => hey
# => That was fun
Thing.new.f2
# => hey
# => That was not fun
But see below the line for a better way.
Annotations (see normalocity's answer) are less trouble and, being a common Ruby idiom, will more easily communicate your code's intent. Here's how to do it with annotations:
module FunNotFun
def fun(method_id)
wrap_method(method_id, "fun")
end
def notfun(method_id)
wrap_method(method_id, "not fun")
end
def wrap_method(method_id, type_of_method)
orig_method = instance_method(method_id)
define_method(method_id) do |*args|
orig_method.bind(self).call(*args).tap do
puts "That was #{type_of_method}"
end
end
end
end
In use, the annotation comes after the method is defined, rather than before:
class Thing
extend FunNotFun
def f1
puts "hey"
end
fun :f1
def f2
puts "hey"
end
notfun :f2
end
The result is the same:
Thing.new.f1
# => hey
# => That was fun
Thing.new.f2
# => hey
# => That was not fun
Sounds like you want to write extensions to the Ruby language itself, which is possible. It's not something that can be explained briefly, but this link should get you started:
http://ruby-doc.org/docs/ProgrammingRuby/html/ext_ruby.html
This reference, having to do with annotations in Ruby, might also be helpful/relevant:
http://martinfowler.com/bliki/RubyAnnotations.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With