As the title suggests, I would like to assign all the instance methods defined on one class to another. I know at I can get a list of the methods that I want to copy from ClassA to ClassB like this:
ClassA.instance_methods(false)
And I think I can define them on ClassB like this:
ClassA.instance_methods(false).each do |method_name|
ClassB.method_define(method_name, [body here??])
end
Is there a way to get the corresponding method body, and if so, will this method work? If not, is there even a way to do this?
Others already told you to subclass. But to answer your literal question, we would be getting involved with UnboundMethod objects:
class Object
def kokot; 'kokot' end
end
o = Object.new
o.kokot
#=> kokot
3.kokot
#=> kokot
So far so good. Now let's redefine kokot method on Numeric:
class Numeric
def kokot; 'pica' end
end
o.kokot
#=> kokot
3.kokot
#=> pica
But what if we decide, that new kokot method is great for numerics, but just complex numbers should keep using the old kokot method. We can do it like this:
um = Object.instance_method :kokot
#=> #<UnboundMethod: Object#kokot>
Complex( 2, 3 ).kokot # gives the redefined kokot method
#=> pica
Complex.module_exec { define_method :kokot, um }
# Now we've just bound the old kokot to Complex
Complex( 2, 3 ).kokot
#=> kokot
In short, there is a way to "copy and paste" methods among related classes. It is required that the target be a subclass of the unbound method source. Method #source_location shows the file and the line where #kokot has been defined:
um.source_location
#=> ["(irb)", 2]
For built-in methods, #source_location returns nil. In Ruby 2.0, RubyVM class has method #disassemble:
RubyVM::InstructionSequence.disassemble( um )
#=> ( program listing goes here )
In any case, Ruby bytecode is not that beautiful to look at. Going back to your original needs, not even #define_method or UnboundMethod#bind can bind methods to incompatible objects. This cannot be cheated by tricks like redefining #kind_of?, one would have to cheat CLASS_OF() function in the native code...
From the available gems, Sourcify, RubyParser and Sorcerer are of interest. (Thanks, #Casper.) Using these, one could theoretically transplant code between incompatible objects via #eval-ling extracted method source. Long way as it goes, this technique would still fall short of realiable method transfer, as it fails whenever the source is not available at runtime (eg. self-modifying source).
It seems like what you might want is mix-ins:
Taken from http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html
module Debug
def whoAmI?
"#{self.type.name} (\##{self.id}): #{self.to_s}"
end
end
class Phonograph
include Debug
# ...
end
class EightTrack
include Debug
# ...
end
ph = Phonograph.new("West End Blues")
et = EightTrack.new("Surrealistic Pillow")
ph.whoAmI? » "Phonograph (#537766170): West End Blues"
et.whoAmI? » "EightTrack (#537765860): Surrealistic Pillow"
In ruby 2.0 you can use modules. Matz explicitly forbade this behavior from classes.
But you can use instance_methods from modules.
ModuleA.instance_methods(false).each do |name|
meth = ModuleA.instance_method(name)
ClassB.send(:define_method, name, meth)
end
define_method is a private method, so that's why you use send here.
But why do this? Just include the module.
If you want to just apply behavior to an object you can unbind a method from any module and bind it to any object.
ModuleA.instance_method(:something).bind(some_object).call(args)
If this is what you want, take a look at casting, a gem that adds a convenience to doing delegation like this as well as adding methods to an object only for the life of a block.
In that case, classB should inherit classA.
Related
I'm not sure where I have seen this, or if I just think I have seen it, but I would like to be able to call a method that creates an instance of a class with the same name. So, instead of:
# The class is called 'Vector3', for example:
Vector3.new(x,y,z)
I would like to have an eponymous method that instantiates the class, like so:
Vector3(x,y,z) #<- returns instance of Vector3 class
How would you define that in Ruby?
As #Eli mentioned, you can define a method in the kernel:
def Kernel.Vector3(*args)
Vector3.new(*args)
end
Ruby does this for Array, Complex, Float, Hash, Integer, Rational and String where you probably saw it.
The reason it works is that Object includes Kernel, hence all objects in your program (except ones directly inheriting from BasicObject) will have that method.
However, doing so is unidiomatic, unnecessary (you clutter all objects with an additional method), confusing (capitalized identifiers should be constants) and generally looked down upon.
AFAIK you can't. You can do something similar, Vector3[x, y, z].
class Vector3
def initialize(x, y, z)
# ...
end
def self.[](*args)
self.new(*args)
end
end
Note that the Ruby library uses this device as well. There's Hash.new(...) and Hash[...] , but no Hash(...). This parallels how Proc objects are invoked:
greet = Proc.new { |name| puts "Hello, #{name}" }
greet["Amadan"]
EDIT: I stand corrected:
module Kernel
def Vector3(*args)
Vector3.new(*args)
end
end
But, as Eli Sadoff said, it is impractical, violates encapsulation, and Ruby style (functions and methods should be lowercase).
This answers what I understood the question to be from the title. (Somehow I overlooked the example that contradicts that.) I will leave my answer because I think it includes some interesting elements.
class MyClass
def hi
"hi"
end
my_alias = to_s
singleton_class.class_eval { alias_method(my_alias, :new) }
end
MyClass.methods(false)
#=> [:MyClass]
my_instance = MyClass.MyClass
#=> #<MyClass:0x007fadc2092320>
my_instance.hi
#=> "hi"
Note that this works when the alias of new is passed arguments and/or a block.
See Object#singleton_class and Module#class_eval.
The number 1 contains 109 additional methods above and beyond the Fixnum class it inherits from.
1.methods - Fixnum.methods => [:%, :&, :*, :**, :+, :+#, :-, :-#, ...]
(1.methods - Fixnum.methods).count => 109
1.is_a? Fixnum => true
So from my understanding, I would say the number 1 is an instance of Fixnum. But why does the number 1 have so many more methods than Fixnum? And where do they come from? How would I write my own method for the number 1?
When you call .methods, it gives the methods defined on that instance. So when you ask for Fixnum.methods, you get the methods you can call on Fixnum the class, not on objects of type Fixnum.
As to your last question, Ruby allows you to extend a class like so:
class Fixnum
def plus9
return self + 9
end
end
They can come from Fixnum's parent classes as well as any modules mixed in along the way. You can use 1.method('<method name>').inspect to find out where exactly does the method originate.
method#source_location is good as well, but it doesn't work for native methods, which is almost everything on 1.
Fixnum itself is an instance of Class, when you call Fixnum.methods, it returns the methods that the Class class and its ancestors have.
So 1.methods - Fixnum.methods has little sense as you are comparing the methods of Fixnum class and the methods of Class class.
Fixnum.class
# => Class
1.class
# => Fixnum
How would I write my own method for the number 1
You can implement your own methods in Fixnum or any of its ancestor classes: Integer, Numeric, etc, depending on which class this method makes sense.
You may misunderstand the Object#methods method.
According to the Ruby API,
methods(regular=true) → Returns a list of the names of public and protected methods of obj.
So Fixnum.methods returns the methods from the perspective of the object, not the class.
Module#instance_methods is what you want
1.methods.count == Fixnum.instance_methods.count # => true
To get the right method list in Ruby is kind of a confusing thing, Idiosyncratic Ruby has a detailed post about method-lists. It helps me sort things up, and hope this can help you, too.
To extend the Fixnum class and add/modify your own methods. You can use this code:
class Fixnum
def newNum_method
puts self.methods
end
end
Also you can modify existing methods the same way. Many times the 'to_s' is modified to produce specific results for example:
class Array
def to_s
puts self.join(":")
end
end
This code ONLY modifies what you specify.
You can also add class specific code for example:
def Array.newMethod
puts Array.methods
end
This allows you to call:
puts Array.newMethod
(Which would technically be the same as "puts Array.methods")
but you can customize this to say or do whatever with the 'Array' class
You could even create a method for the Fixnum class itself to Iterate over its parents and list EACH method from them.
def Fixnum.listParentMethods
.....
end
Try
1.methods - Fixnum.instance_methods
and you'll get an empty array.
In ruby, classes are objects of type Class.
When you call obj.methods, it returns all public methods of obj.
So what if obj is a class?
Just want to enquire what the right practice is.
My preference is to use procs, simply because I think that defining methods inside of methhods is a bit untidy and should be done only when necessary. To get around it, I simply use procs.
What is the right / better way to do it and why? (apart from the proc's ability to access the main method's variables defined before itself)
def meth( params_prime )
calculations = do_something_with_whatever
def sub_meth( params_sub )
do_something_with_params_sub
end
sub_meth_params(calculations) # is this better?
proc1 = proc{ |params_sub| do_something_with_params_sub }
proc1.call(calculations) # or is this?
end
It is not clear what your specific use-case is, but I would definitely go for procs or lambdas. There is less overhead when defining a proc or lambda dynamically, they are passable, so if needed you could return them and they could be used outside the function.
Using "def" exposes the method as an instance method outside of the current method scope (so in the containing class, which could be Object in your case). This may or may not be with you want. If you want to use an anonymous function only available in the local scope, use a lambda.
Also Proc vs Lambda: I generally prefer to use lambdas since they behave a little more "predictable", meaning: as you would expect (check passed variables, and return just returns from the lambda, proc returns from the called scope). But from your example it is hard to deduce what would apply. I think the key-difference is: lambas are ment to be passed around, and thus behave a little more sanely. If this is not your use-case, use Proc :) (a write-up of the difference).
If you want to use sub_func to encapsulate it from call from other methods you can use a class to group function and sub_func together and make sub_func private. Otherwise if you want to pass this function as a parameter further you can declare it as lamda.
def func params_prime
sub_func = ->(params_sub){do_something_with_params}
sub_func.call(params_prime)
end
Defining methods inside methods is a feature of Ruby that may have its use. But something is telling me that you are asking a very advanced question while you are still a beginner level Rubyist. Do you know what default definee is? If not, check this article by Yugui.
Procs are very important in Ruby, but newbies tend to use them instead of defining methods in appropriate objects, which is the exact smell I'm getting from your question. The normal way of doing things in OO languages of Ruby family is to define methods on objects:
class Foo
def bar *params
# do something with params
end
end
Since you do not understand the meaning of defining methods inside methods, refrain from doing it for the next 6 months. Once you understand objects, you can start experimenting with this very advanced feature again.
APPENDIX:
Since you demonstrated intrest, let me show you that using def in def at the top level is a frownable-upon thing to do. Normally, when you define a method on some class without further adornment, it becomes a public instance method of that class:
class X
def foo; "foo" end
end
X.instance_methods.include? :foo
#=> true
When you use def in a def, the definee for the inner def is going to be X:
class X
def bar
def baz
"baz"
end
"bar"
end
end
When you execute the above code, instance method #bar becomes defined on X:
X.instance_methods.include? :bar
#=> true
But #baz not yet:
X.instance_methods.include? :baz
#=> false
Only after you call #bar at least once does the method become defined on X:
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
And now I would like to ask you to appreciate how terrible thing just happened: An instance just modified its mother class. That's a violation. A violation of such a basic principle of OO design, that I'm not even sure it has a name. This technique is great for obfuscated coding competitions, but in production, it's taboo. Ruby gives you the freedom to break that taboo, gives you the rope to hang yourself on, but you don't do it under any kind of normal circumstances.
So what can be worse than a def inside a def in a class definition? The answer is, a def inside a def at the top level. Let me show you why. Normally, when you define methods with def at the top level, the default definee is Object, but the top level defnitions become private instance methods of object. This is to prevent the unintended consequence of top level defs, because almost all Ruby objects inherit from Object. For example, if you define:
class Object
def foo; "foo" end
end
Now all your objects will respond to foo:
foo #=> "foo"
1.foo #=> "foo"
[].foo #=> "foo
When we define methods at the top level, we usually just intend to use the method at the top level, and don't want every single object to inherit it. For that reason, top level defs become private:
hello #=> NameError: undefined local variable or method `hello' for main:Object
1.hello #=> NoMethodError: undifined method 'hello' for 1:Fixnum
Now we use def at the top level:
def hello; "hello" end
We can see that method #hello is has not become an instance methods of Object:
Object.instance_methods.include? :hello
#=> false
Mysteriously, it became its private method:
Object.private_instance_methods.include? :hello
#=> true
This way, we avoid the unintended consequence of defining #hello method for every single object. But the inheritance is there. The error message has changed:
1.hello #=> NoMethodError: private method 'hello' called for 1:Fixnum
And we can forcibly call the method via #send:
1.send :hello
#=> "hello"
Mysteriously, at the top level, we are allowed to call this private method without #send:
hello
#=> "hello"
And now, what happens when you do def in def at the top level:
def bar
def baz; "baz" end
"bar"
end
You define a private instance method Object#bar in an expected way. But when you call it, alas, the top level magic no longer works and a public method Object#baz gets defined:
bar #=> "bar"
This way, not just the top level, but every single Ruby object got polluted with your #baz method:
1.baz #=> "baz"
Class.baz #=> "baz"
This is why I told you to refrain from using this idiom until you progress from the level of unconscious incompetence to the level of conscious incompetence. I recommend you to read more about top level methods in Ruby.
I know in Ruby that I can use respond_to? to check if an object has a certain method.
But, given the class, how can I check if the instance has a certain method?
i.e, something like
Foo.new.respond_to?(:bar)
But I feel like there's gotta be a better way than instantiating a new instance.
I don't know why everyone is suggesting you should be using instance_methods and include? when method_defined? does the job.
class Test
def hello; end
end
Test.method_defined? :hello #=> true
NOTE
In case you are coming to Ruby from another OO language OR you think that method_defined means ONLY methods that you defined explicitly with:
def my_method
end
then read this:
In Ruby, a property (attribute) on your model is basically a method also. So method_defined? will also return true for properties, not just methods.
For example:
Given an instance of a class that has a String attribute first_name:
<instance>.first_name.class #=> String
<instance>.class.method_defined?(:first_name) #=> true
since first_name is both an attribute and a method (and a string of type String).
You can use method_defined? as follows:
String.method_defined? :upcase # => true
Much easier, portable and efficient than the instance_methods.include? everyone else seems to be suggesting.
Keep in mind that you won't know if a class responds dynamically to some calls with method_missing, for example by redefining respond_to?, or since Ruby 1.9.2 by defining respond_to_missing?.
Actually this doesn't work for both Objects and Classes.
This does:
class TestClass
def methodName
end
end
So with the given answer, this works:
TestClass.method_defined? :methodName # => TRUE
But this does NOT work:
t = TestClass.new
t.method_defined? : methodName # => ERROR!
So I use this for both classes and objects:
Classes:
TestClass.methods.include? 'methodName' # => TRUE
Objects:
t = TestClass.new
t.methods.include? 'methodName' # => TRUE
The answer to "Given a class, see if instance has method (Ruby)" is better. Apparently Ruby has this built-in, and I somehow missed it. My answer is left for reference, regardless.
Ruby classes respond to the methods instance_methods and public_instance_methods. In Ruby 1.8, the first lists all instance method names in an array of strings, and the second restricts it to public methods. The second behavior is what you'd most likely want, since respond_to? restricts itself to public methods by default, as well.
Foo.public_instance_methods.include?('bar')
In Ruby 1.9, though, those methods return arrays of symbols.
Foo.public_instance_methods.include?(:bar)
If you're planning on doing this often, you might want to extend Module to include a shortcut method. (It may seem odd to assign this to Module instead of Class, but since that's where the instance_methods methods live, it's best to keep in line with that pattern.)
class Module
def instance_respond_to?(method_name)
public_instance_methods.include?(method_name)
end
end
If you want to support both Ruby 1.8 and Ruby 1.9, that would be a convenient place to add the logic to search for both strings and symbols, as well.
Try Foo.instance_methods.include? :bar
Not sure if this is the best way, but you could always do this:
Foo.instance_methods.include? 'bar'
I think there is something wrong with method_defined? in Rails. It may be inconsistent or something, so if you use Rails, it's better to use something from attribute_method?(attribute).
"testing for method_defined? on ActiveRecord classes doesn't work until an instantiation" is a question about the inconsistency.
If you're checking to see if an object can respond to a series of methods, you could do something like:
methods = [:valid?, :chase, :test]
def has_methods?(something, methods)
methods & something.methods == methods
end
the methods & something.methods will join the two arrays on their common/matching elements. something.methods includes all of the methods you're checking for, it'll equal methods. For example:
[1,2] & [1,2,3,4,5]
==> [1,2]
so
[1,2] & [1,2,3,4,5] == [1,2]
==> true
In this situation, you'd want to use symbols, because when you call .methods, it returns an array of symbols and if you used ["my", "methods"], it'd return false.
klass.instance_methods.include :method_name or "method_name", depending on the Ruby version I think.
class Foo
def self.fclass_method
end
def finstance_method
end
end
foo_obj = Foo.new
foo_obj.class.methods(false)
=> [:fclass_method]
foo_obj.class.instance_methods(false)
=> [:fclass_method]
Hope this helps you!
While respond_to? will return true only for public methods, checking for "method definition" on a class may also pertain to private methods.
On Ruby v2.0+ checking both public and private sets can be achieved with
Foo.private_instance_methods.include?(:bar) || Foo.instance_methods.include?(:bar)
On my case working with ruby 2.5.3 the following sentences have worked perfectly :
value = "hello world"
value.methods.include? :upcase
It will return a boolean value true or false.
Let there be class Example defined as:
class Example
def initialize(test='hey')
self.class.send(:define_method, :say_hello, lambda { test })
end
end
On calling Example.new; Example.new I get a warning: method redefined; discarding old say_hello. This, I conclude, must be because it defines a method in the actual class (which makes sense, from the syntax). And that, of course, would prove disastrous should there be multiple instances of Example with different values in their methods.
Is there a way to create methods just for the instance of a class from inside that instance?
You need to grab a reference to the instance's singleton class, the class that holds all the instance specific stuff, and define the method on it. In ruby 1.8, it looks a little messy. (if you find a cleaner solution let me know!)
Ruby 1.8
class Example
def initialize(test='hey')
singleton = class << self; self end
singleton.send :define_method, :say_hello, lambda { test }
end
end
Ruby 1.9 however, provides a much easier way in.
Ruby 1.9
class Example
def initialize(test='hey')
define_singleton_method :say_hello, lambda { test }
end
end
First off, a small style tip:
self.class.send(:define_method, :say_hello, lambda { test })
You can make this look a little bit nicer by using the new proc literal in Ruby 1.9:
self.class.send(:define_method, :say_hello, -> { test })
But you don't need that. Ruby has something called blocks, which are basically a piece of code that you can pass as an argument to a method. In fact, you already used blocks, since lambda is just a method which takes a block as an argument and returns a Proc. However, define_method already takes a block anyway, there is no need to pass a block to lambda which converts it to a Proc which it passes to define_method which then converts it back into a block:
self.class.send(:define_method, :say_hello) { test }
As you already noticed, you are defining the method on the wrong class. You are defining it on the Example class, since inside an instance method like initialize, self is the current object (i.e. ex1 or ex2 in #mikej's example), which means that self.class is ex1's class, which is Example. So, you are overwriting the same method over and over again.
This leads to the following unwanted behavior:
ex1 = Example.new('ex1')
ex2 = Example.new('ex2') # warning: method redefined; discarding old say_hello
ex1.say_hello # => ex2 # Huh?!?
Instead, if you want a singleton method, you need to define it on the singleton class:
(class << self; self end).send(:define_method, :say_hello) { test }
This works as intended:
ex1 = Example.new('ex1')
ex2 = Example.new('ex2')
ex1.say_hello # => ex1
ex2.say_hello # => ex2
In Ruby 1.9, there's a method that does that:
define_singleton_method(:say_hello) { test }
Now, this works the way you want it to, but there's a higher-level problem here: this is not Ruby code. It is Ruby syntax, but it's not Ruby code, it's Scheme.
Now, Scheme is a brilliant language and writing Scheme code in Ruby syntax is certainly not a bad thing to do. It beats the hell out of writing Java or PHP code in Ruby syntax, or, as was the case in a StackOverflow question yesterday, Fortran-57 code in Ruby syntax. But it's not as good as writing Ruby code in Ruby syntax.
Scheme is a functional language. Functional languages use functions (more precisely, function closures) for encapsulation and state. But Ruby is not a functional language, it is an object-oriented language and OO languages use objects for encapsulation and state.
So, function closures become objects and captured variables become instance variables.
We can also come at this from a completely different angle: what you are doing is that you are defining a singleton method, which is a method whose purpose it is to define behavior which is specific to one object. But you are defining that singleton method for every instance of the class, and you are defining the same singleton method for every instance of the class. We already have a mechanism for defining behavior for every instance of a class: instance methods.
Both of these arguments come from completely opposite directions, but they arrive at the same destination:
class Example
def initialize(test='hey')
#test = test
end
def say_hello
#test
end
end
I know it was asked two years back, but I would like to add one more answer. .instance_eval will help to add methods to instance object
string = "String"
string.instance_eval do
def new_method
self.reverse
end
end
Define instance method from outside:
example = Example.new
def example.say_hello
puts 'hello'
end
From inside:
class Example
def initialize(word='hey')
#word = word
def self.say_hello
puts "example: #{#word}"
end
end
end
Tested on ruby 2.5