Class.new.new
# => #<#<Class:0x44f3a2>:0xd7244e>
I am curious to know what is created. Is it an object of object? Any technical explanation will be appreciated.
With Class.new you are creating a new class. In fact not only you can create classes via the common syntax:
class Bird
def is
"word"
end
end
but you can also use Class::new like this:
Bird = Class.new do
def is
"word"
end
end
In the above example you can run Bird.new.is and it will return "word" just like in the first example.
It is useful to create anonymous classes or classes that you can rename at your will.
In your case:
Class.new.new
By simply calling Class.new you are creating a new anonymous class with no custom methods or instance variables which is then later instantiated via the second new method.
You can follow it through in the console:
irb(main):011:0> c = Class.new
=> #<Class:0x000000028245e0>
c is a new class.
irb(main):012:0> c.new
=> #<#<Class:0x000000028245e0>:0x0000000282a170>
Calling c.new returns you a new instance of the new class you just created.
Class.new creates and returns Class instance (which is class). If you call on it new again, previously created class will be instantiated.
my_class = Class.new # makes a new class which is a subclass of Object
my_instance = my_class.new # makes a new instance object of the class
Related
I'm trying to dynamically add methods to a single instance of a class, and then be able to instantiate new objects of that modified class.
Below is a sketch of what I'm trying to accomplish.
class A
def add_new_method
define_singleton_method(:new_method) { puts("hi") }
end
end
a = A.new
a.add_new_method
B = a.singleton_class
b = B.new
Obviously, the above is reasonably impossible with those methods since you clearly shouldn't be able to create a new instance of a singleton. What is the right way to accomplish the same?
You can't instantiate singleton classes in Ruby but you can write some code to get the feeling you are doing it.
I would use a class method as the following example
class A
def add_new_method
define_singleton_method(:new_method) { puts("hi") }
self
end
def self.Enhanced
new.add_new_method
end
end
b = A.Enhanced
b.new_method
# hi
Given the following code below:
class Animal
end
dog = Animal.new # --> return value of Animal.new
What are the specific methods to retrieve the return value for Animal.new? I understand that a new instance is created from the class Animal and assigned to the variable dog. But what are the methods to retrieve the return value of Animal.new?
According to docs here:
new(args, ...) → obj
Calls allocate to create a new object of class’s class, then invokes
that object’s initialize method, passing it args. This is the method
that ends up getting called whenever an object is constructed using
.new.
You can test this yourself in irb. It returns an instance of that object.
# Instantiating a new instance of a class
irb(main):001:0> Class.new
=> #<Class:0x007fe24193c918>
# Assigning a new instance of a class to a variable
irb(main):005:0> some_var = Class.new
=> #<Class:0x007fe2410e68b8>
irb(main):006:0> some_var
=> #<Class:0x007fe2410e68b8>
class A
end
Calling a = A.new return the new object of class A, the string appear as eg #<A:0x00000002d8eb98> is the string containing human readable representation of the object from the default implementation of inspect method which is called each time new object is created.
The default inspect shows the object’s class name, an encoding of the object id and a list of the instance variables and their values User custom classes eg A should/adviced to override this method to provide better representation of their objects eg
class A
def inspect
"I am what i am"
end
end
b = A.new
prints -> I am what i amnot the hexadecimal value
In the following example everything is logical for me:
class Something
def initialize
#x=101
end
def getX
return #x
end
end
obj = Something.new
puts obj.getX
=>101
Something.new will create new instance of class Something with instance variable #x which will be visible to all methods of class Something.
But what will happen in second example without initialize(constructor) method.
class Something
def bla_bla_method
#x=101
end
def getX
return #x
end
end
obj = Something.new
puts obj.getX
=>nil
obj.bla_bla_method
puts obj.getX
=>101
So now bla_bla_method when called will create(like constructor) new instance_variable #x and will add that instance variable in "instance variable table" which is available to all methods again?
So now if i add new method "new_method" in class Something(in second example):
def new_method
#x=201
end
...
obj.bla_bla_method
puts obj.getX
=>101
obj.new_method
puts obj.getX
=>201
So if im getting this right, every method of class can create new instance variable which is available to all methods of class? And then every method can overwrite that instance variable over and over again(cyclical)?
I'm new to ruby so maybe here i'm doing big mistake or don't understand some basic concept , so dont yell :D
Instance variables for an object can be named and manipulated while the object exists. See the example below, when we are using the irb prompt object:
$ irb
> instance_variables # => [:#prompt]
> #foo # => nil
> instance_variables # => [:#prompt]
> #foo = 1 # => 1
> instance_variables # => [:#prompt, :#foo]
> #foo # => 1
Now, here's a description of Class#new from the docs:
Calls allocate to create a new object of class’s class, then invokes that object’s initialize method, passing it args. This is the method that ends up getting called whenever an object is constructed using .new.
One way to think of this is that initialize is functionally a regular method just like your other instance methods, only it gets called by Class#new to provide us with an easy way of setting default values (among others).
Technically, yes. But consider the notion of Object Oriented programming - Creating real world abstractions in form of classes and objects.
For instance, if you are talking about a student in a school; you know that is an abstractable entity. So you go ahead and encapsulate the common characteristic of student in a class Student.
initialize is a constructor. When you create a new student in your system, you would naturally want to supply few necessary details about him like his name, age and class.
So in initialize method you set those instance variables.
Few students also study in school; so naturally they will acquire some grade and stuff; to instantiate those details about the student, you would want to do that with something like this:
#Student(name, age, class)
kiddorails = Student.new("Kiddorails", 7, 2)
#to grade:
kiddorails.set_grades
#do stuff
So you can mutate and set the instance variables in an object, almost anywhere you want in a class; but the point is - Do it, where it makes sense.
PS: You should always set default values to the instance variables which are not set via initialize in initialize, if needed.
I need to create a class that prevents outside code from instantiating it directly. All instances are obtained by calling a couple of class methods, and also some instance methods that will generate new instances and return them.
class SomeClass
class << self
private :new, :allocate
end
def initialize(hash)
#hash = hash
end
# A class method that returns a new instance
def self.empty
new({}) # works fine!
end
# Another class method that returns a new instance
def self.double(a, b)
new({a => b}) # works fine!
end
# An instance method that will generate new instances
def combine_with(a, b)
# Here's the problem!
# Note: it doesn't work with self.class.new either
SomeClass.new(#hash.merge({a => b}))
end
end
So I defined the new method to be private. This works for the class methods, inside of them I can still call new internally. But I can't call new from within the instance methods. I tried defining new as protected, but this didn't help either.
did you try to use send?
SomeClass.send :new, #hash.merge({a => b})
I'm stuck. I'm trying to dynamically define a class method and I can't wrap my head around the ruby metaclass model. Consider the following class:
class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
end
Example.class_instance.class # => Class
Example.meta.class # => Class
Example.class_instance == Example # => true
Example.class_instance == Example.meta # => false
Obviously both methods return an instance of Class. But these two instances
are not the same. They also have different ancestors:
Example.meta.ancestors # => [Class, Module, Object, Kernel]
Example.class_instance.ancestors # => [Example, Object, Kernel]
What's the point in making a difference between the metaclass and the class instance?
I figured out, that I can send :define_method to the metaclass to dynamically define a method, but if I try to send it to the class instance it won't work. At least I could solve my problem, but I still want to understand why it is working this way.
Update Mar 15, 2010 13:40
Are the following assumptions correct.
If I have an instance method which calls self.instance_eval and defines a method, it will only affect the particular instance of that class.
If I have an instance method which calls self.class.instance_eval (which would be the same as calling class_eval) and defines a method it will affect all instances of that particular class resulting in a new instance method.
If I have a class method which calls instance_eval and defines a method it will result in a new instance method for all instances.
If I have a class method which calls instance_eval on the meta/eigen class and defines a method it will result in a class method.
I think it starts to make sense to me. It would certainly limit your possibilities if self inside an class method would point to the eigen class. If so it would not be possible to define an instance method from inside a class method. Is that correct?
Defining a singleton method dynamically is simple when you use instance_eval:
Example.instance_eval{ def square(n); n*n; end }
Example.square(2) #=> 4
# you can pass instance_eval a string as well.
Example.instance_eval "def multiply(x,y); x*y; end"
Example.multiply(3,9) #=> 27
As for the difference above, you are confusing 2 things:
The meta class defined by you, is what called in Ruby community as singelton class or eigen class. That singleton class is the class that you can add class(singleton) methods to.
As for the class instance you are trying to define using the class_instance method, is nothing but the class itself, to prove it, just try adding an instance method to the class Example and check if the class_instance method defined by you returns the class Example itself by checking the existence of that method:
class Example
def self.meta; (class << self; self; end); end
def self.class_instance; self; end
def hey; puts hey; end
end
Example.class_instance.instance_methods(false) #=> ['hey']
Anyway to sum it for you, when you want to add class methods, just add them to that meta class. As for the class_instance method is useless, just remove it.
Anyway I suggest you read this post to grasp some concepts of Ruby reflection system.
UPDATE
I suggest you read this nice post: Fun with Ruby's instance_eval and class_eval,
Unfortunately class_eval and instance_eval are confusing because they somehow work against their naming!
Use ClassName.instance_eval to define class methods.
Use ClassName.class_eval to define instance methods.
Now answering your assumptions:
If I have an instance method which
calls self.instance_eval and defines a
method, it will only affect the
particular instance of that class.
yes:
class Foo
def assumption1()
self.instance_eval("def test_assumption_1; puts 'works'; end")
end
end
f1 = Foo.new
f1.assumption1
f1.methods(false) #=> ["test_assumption_1"]
f2 = Foo.new.methods(false) #=> []
If I have an instance method which
calls self.class.instance_eval (which
would be the same as calling
class_eval) and defines a method it
will affect all instances of that
particular class resulting in a new
instance method.
no instance_eval in that context will define singleton methods(not instance ones) on the class itself:
class Foo
def assumption2()
self.class.instance_eval("def test_assumption_2; puts 'works'; end")
end
end
f3 = Foo.new
f3.assumption2
f3.methods(false) #=> []
Foo.singleton_methods(false) #=> ["test_assumption_2"]
For that to work replace instance_eval with class_eval above.
If I have a class method which calls
instance_eval and defines a method it
will result in a new instance method
for all instances.
Nope:
class Foo
instance_eval do
def assumption3()
puts 'works'
end
end
end
Foo.instance_methods(false) #=> []
Foo.singleton_methods(false) #=> ["assumption_3"]
That will make singleton methods, not instance methods. For that to work replace instance_eval with class_eval above.
If I have a class method which calls
instance_eval on the meta/eigen class
and defines a method it will result in
a class method.
well no, that will make so sophisticated stuff, as it will add singleton method to the singleton class, I don't think that will have any practical use.
If you define a method on a class, it can be invoked on its objects. It is an instance method.
class Example
end
Example.send :define_method, :foo do
puts "foo"
end
Example.new.foo
#=> "foo"
If you define a method on a metaclass, it can be invoked on the class. This is similar to the concept of a class method or static method in other languages.
class Example
def self.metaclass
class << self
self
end
end
end
Example.metaclass.send :define_method, :bar do
puts "bar"
end
Example.bar
#=> "bar"
The reason that metaclasses exist is because you can do this in Ruby:
str = "hello"
class << str
def output
puts self
end
end
str.output
#=> "hello"
"hi".output
# NoMethodError
As you can see, we defined a method that is only available to one instance of a String. The thing that we defined this method on is called the metaclass. In the method lookup chain, the metaclass is accessed first before searching the object's class.
If we replace the object of type String with an object of type Class, you can imagine why this means we're only defining a method on a specific class, not on all classes.
The differences between the current context and self are subtle, you can read more if you're interested.