Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is the "public/protected/private" method implemented, and how can I emulate it?

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

like image 819
A Question Asker Avatar asked Oct 12 '11 22:10

A Question Asker


People also ask

What is the difference between public private and protected methods?

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?

What is a public method in Java?

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.

What are protected methods in Java?

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...

What is public private and protected in Python?

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.


2 Answers

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
like image 101
Wayne Conrad Avatar answered Oct 24 '22 00:10

Wayne Conrad


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

like image 32
jefflunt Avatar answered Oct 24 '22 01:10

jefflunt