I want a class that does not support instantiation via new, like the Integer class. I tried to inherit from BasicObject, but it still lets me create an instance with new.
You have several options, which I will present here (roughly) in the order of how "aggressive" they are in my personal opinion:
Override the default Object#initialize with your own
You can override the default implementation of Object#initialize with your own implementation which does something different. In your case, say, raise an Exception:
class Foo
def initialize(*) raise TypeError, "`#{self.class}` cannot be instantiated." end
end
Foo.new
# TypeError: `Foo` cannot be instantiated.
# from (…):5:in `initialize'
The default implementation of Class#new will automatically call your implementation of Foo#initialize, which will then raise an Exception and abort the object construction, or more precisely: it will abort the object initialization, since the object will have been constructed by the time initialize is called (otherwise, how would you call initialize if there is no object to call it on?) However, object construction is cheap, and the object will immediately be eligible for garbage collection, so it shouldn't matter.
For completeness' sake, here is (approximately) what the default implementation of Class#new looks like:
class Class
def new(*args, &b)
obj = allocate
obj.send(:initialize, *args, &b) # `initialize` is `private`, must use `send`
obj
end
end
As you can see, by the time initialize is called, Class#allocate will have already constructed the object.
Override the default Class#new with your own
You can override the default implementation of Class#new with your own implementation which does something different. In your case, say, raise an Exception:
def Foo.new(*) raise TypeError, "`#{self}` cannot be instantiated." end
Foo.new
# TypeError: `Foo` cannot be instantiated.
# from (…):3:in `new'
Make Foo::new a private method
You can make the new method of the singleton class of Foo a private method, that way, it can't be called with an explicit receiver:
Foo.private_class_method :new
Foo.new
# NoMethodError: private method `new' called for Foo:Class
# from (…):3:in `…'
This would, for example, still allow you to have special factory methods that construct instances of your class, e.g. something like:
def Foo.create_from_xml(file)
# do stuff to parse `file`
new(argument_parsed_from_file)
end
Note this sentence in the documentation of Module#private_class_method:
Often used to hide the default constructor new.
and the code example directly following it.
Undefine the new method from the singleton class of Foo
You could undefine the new method using Module#undef_method. undef_method will prevent instances of the module from responding to that message completely, unlike Module#remove_method, which will simply remove the method from the module, so that method lookup continues normally up the inheritance chain.
Foo.singleton_class.undef_method :new
Foo.new
# NoMethodError: undefined method `new' for Foo:Class
# from (…):3:in `…'
How about this?
module MyClassWithOnlyClassMethods
extend self
def foo
end
end
Actually, you can do it without extend self, but you would have then to write def self.foo etc. for each method, which gets cumbersome.
Related
Hey guys I am new to Ruby. I have a question: Do methods have to be always inside classes?
Technically they are aways defined inside a class, but this doesn't mean you always need to open a class to define a method.
Here is what might look like a top-level function in other languages:
def foo
puts self
puts self.class
end
If we simply call foo, we'll get:
main
Object
This actually defined a private instance method in the Object class. We see that self in the top-level scope is a special object called main.
On the other hand, we can try to call this method on other stuff:
'bar'.foo #!> private method `foo' called for "bar":String (NoMethodError)
This errorred out as foo is private. We can use a special method called send to invoke private methods:
'bar'.send :foo
Gets us:
bar
String
We can also define methods in the so-called singleton classes. You can think of them as classes with only a single instance. For example:
foo = 'foo'
def foo.bar
puts 'baz'
end
foo.bar # => baz
'quix'.bar # !> undefined method `bar' for "quix":String
'foo'.bar # !> undefined method `bar' for "foo":String
puts (foo.singleton_class.instance_methods - Object.instance_methods).first
# => bar
Here the bar method was defined on the singleton class of foo. Note that even another string with the same contents is still a difference instance, hence it doesn't have the bar method.
Hey guys I am new to Ruby. I have a question: Do methods have to be always inside classes?
No.
Methods have to be always inside modules. (Class are modules, too.)
Example:
module Foo
def bar; end
end
There is no class here.
Ruby's Class class lists two methods named 'new':
Class::new is a public class method
Class#new is a public instance method
But when I do:
Class.methods(false)
#=> []
which is supposed to list singleton methods (which I am assuming what class methods are), I get an empty array. Why is this so? Where is Class::new defined?
The methods shown as ::new in the documentation are usually #initialize, for example Range::new:
new(begin, end, exclude_end=false) → rng
Constructs a range using the given begin and end. If the exclude_end parameter is omitted or is false, the rng will include the end object; otherwise, it will be excluded.
This is because you create instances via:
r = Range.new(0, 2) #=> 0..2
Rather than:
r = Range.allocate #=> nil..nil
r.send(:initialize, 0, 2) #=> nil
r #=> 0..2
That's exactly what ::new does – it creates a new instance via allocate, sends it initialize (passing arguments) and returns the instance.
The actual new method is inherited from Class (since Range is an instance of Class) – Class#new:
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.
Just like allocate, inherited and superclass (and the instance methods from Class' ancestors like Module as well):
Range.method(:new)
#=> #<Method: Class#new>
Range.method(:allocate)
#=> #<Method: Class#allocate>
Range.method(:ancestors)
#=> #<Method: Class(Module)#ancestors>
So if you call Class.new:
my_string_class = Class.new(String)
#=> #<Class:0x007fdf5485b200>
you just invoke Class#new which is (again) equivalent to:
my_string_class = Class.allocate
my_string_class.send(:initialize, String)
my_string_class
#=> #<Class:0x007fdf5484beb8>
One notable exception is Struct which in fact provide its own new class method:
Struct.method(:new)
#=> #<Method: Struct.new>
Unlike other classes, Struct::new does not return instances of Struct but instances of Class (which are subclasses of Struct).
tl;dr summary:
Why is this so?
Because it's not a singleton method.
Where is Class::new defined?
It isn't. The call Class.new is just calling Class#new (since Class is an instance of itself). The documentation for Foo::new is actually the documentation for Foo#initialize for any class Foo, including Class itself.
If you want to know something about Ruby, it is often a good idea to ask her herself:
new_method = Class.method(:new)
#=> #<Method: Class#new (defined in Class at core/alpha.rb:90)>
The Object#method method returns a Method object representing the method. (Methods aren't objects in Ruby themselves, but you can get a reflective proxy object that represents a method.)
You can ask a Method where it is defined using the Method#owner method:
new_method.owner
#=> Class
As you can see, new is defined in Class and not in Class's singleton class.
You can also ask a Method about the location of its Ruby source code using the Method#source_location method:
new_method.source_location
#=> ['core/alpha.rb', 90]
What this tells us is that Class#new is defined in the file core/alpha.rb on line 90:
def new(*args)
obj = allocate()
Rubinius.asm(args, obj) do |args, obj|
run obj
run args
push_block
send_with_splat :initialize, 0, true
# no pop here, as .asm blocks imply a pop as they're not
# allowed to leak a stack value
end
obj
end
The method is partially implemented in bytecode for performance reasons, but it is basically just:
class Class
def new(*args, &block)
obj = allocate
obj.__send__(:initialize, *args, &block) # because initialize is private
#obj.initialize(*args, &block)
obj
end
end
Now, you might ask yourself: why is there an entry for Class::new in the RDoc documentation, if that method doesn't exist? Well, RDoc knows about the relationship between #initialize which is the method you define but usually don't call directly and Class#new which is the method you call but usually don't define, and it will document #initialize as ::new if it exists.
So, what we really want to look at, is Class#initialize:
initialize_method = Class.method(:initialize)
#=> #<Method: Class#initialize (defined in Class at core/class.rb:15)>
initialize_method.owner
#=> Class
initialize_method.source_location
#=> ['core/class.rb', 15]
This is the source:
def initialize(sclass=Object, name=nil, under=nil)
raise TypeError, "already initialized class" if #instance_type
raise TypeError, "can't make subclass of Class" if Class.equal?(sclass)
set_superclass sclass
# Things (rails) depend on the fact that a normal class is in the constant
# table and have a name BEFORE inherited is run.
under.const_set name, self if under
if sclass
Rubinius.privately do
sclass.inherited self
end
end
super()
end
private :initialize
Class#initialize essentially does three things:
set the superclass
optionally assign the class to a constant to give it a name
call the Class#inherited hook method of the superclass
If you want to know what the relationships between some of the core classes that magically spring into existence at the beginning are, you can take a look at the initialization code of some Ruby execution engines, e.g.
Rubinius: VM::bootstrap_class in machine/ontology.cpp
JRuby: org.jruby.Ruby.initRoot in core/src/main/java/org/jruby/Ruby.java
IronRuby: the initial classes are generated by a program, the generator is in the directory Src/ClassInitGenerator
MRuby: mrb_init_class in src/class.c
Note: depending on what Ruby implementation you use, obviously the places where those methods are defined and how exactly they are defined may vary.
new is defined as a instance method of Class class, rather than a singleton method:
Class.instance_method :new # => #<UnboundMethod: Class#new>
Tricky to note: Class (object) itself is also an instance of Class (class).
Class.instance_of? Class # => true
I'm near the finish of the Ruby track in Code Academy, and I'm curious about a peculiar thing: I was under the impression that a class is a repository of constants, methods, etc... and that in order to access most of them, you would first need to create an instance of that class or in some cases the methods of themselves can be invoked (as in they are all technically part of the global object). And then I saw something like this:
#Worked
Time.now
I understood as this as the method [now] of instance of class [Time] being invoked. I then tried to invoke the method on its own:
#Failed
now
and that failed, and I assumed that while a method can be created in the general scope [as part of the global object], if it relies on initialized variables of "parent" class, it cannot be called on its own, because it would not know which object to search for those initialized variables. Following that I created a test class:
class Clock
def initialize
#hours = 1
#minutes = 30
end
def showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
#this worked
watch = Clock.new
watch.showTime
#this failed
showTime
I then just created a basic method (assuming it's in the global level)
def mymethod
puts "The mighty METHOD!"
end
#Works
mymethod
and calling this method the way I did, without referencing the global object worked. So... the questions I have are as follows:
How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
Why can't I call the method [now] on its own? Am I right that it relies on resources that it cannot find when called this way?
Why could I not call the method showTime on its own? But if I define any method on the "global" level I can access it without referencing the global object
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object class and hence seem to be globally available. Why? From any context Object is always in the class hierarchy of self and hence private methods on Object are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class class and may have singleton methods.
class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods are
class A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name) as follows
str = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on Enumerable) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again.
This is known as a class method. If CodeAcademy didn't cover it, that's a shame. Here's some examples:
# basic way
class Foo
def self.bar; :ok; end
end
Foo.bar # => :ok
# alternate syntax
class Foo
class << self
def bar; :ok; end
end
end
# alternate syntax, if Foo class already exists
def Foo.bar; :ok; end
# alternate approach if Foo class already exists
Foo.class_exec do
def bar; :ok; end
end
# to define a class method on an anonymous 'class' for a single instance
# you won't need to use this often
Foo.new.singleton_class.class_exec do
def bar; :ok; end
end
# to define a class method on an instance's actual class
Foo.new.class.class_exec do
def bar; :ok; end
end
Another way to get class methods is to extend a module.
module FooMethods
def bar; :ok; end
end
module Foo
extend FooMethods
end
Foo.bar # => :ok
Note that with Modules, the methods are always defined as instance methods. This way they can be either extended into class scope or included into instance scope. Modules can also have class methods, using the exact same syntax / examples as shown above with classes. However there's not such as easy to load a module's class methods via include or extend.
How can [Time.now] be called in this fashion? Shouldn't there be an
instance of Time first created?
The Time.now method is a class method, not an instance method and therefore can be called directly on the Time class rather than an instance of it Time.new
Class methods are defined on the class themselves using the self keyword:
class Time
def self.now
# code
end
end
Time.now # works
Why can't I call the method [now] on its own? Am I right that it
relies on resources that it cannot find when called this way?
When you call a method "on its own" you're actually implicitly calling it on self:
self.now
The above is the same as just doing:
now
Why could I not call the method showTime on its own? But if I define
any method on the "global" level I can access it without referencing
the global object
You defined the showTime method on a specific class so you have to send that method to that class. When you define a method in the "global" scope you're implicitly defining it on self and the subsequent call to mymethod is actually self.mymethod so it will work.
Time.now is a class method.
To define a class method, you need to define the method with self. : def self.method_name
class Clock
#hours = 1
#minutes = 30
def self.showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
Clock.showTime
#=> The time is: 1:30
If you want to call now on its own, you can do so inside Time class :
class Time
puts now
#=> 2017-01-19 22:17:29 +0100
end
Suppose I have the following simple class:
class C
p self # => C
def self.foo
puts "foo"
end
def bar
puts "bar"
end
end
p C.foo # => "foo"
p C.bar # => "`<main>': undefined method `bar' for C:Class (NoMethodError)"
I know that self.foo defines foo to be an instance method inside the singleton class of C.
Why does the second method not get defined inside the singleton class of C like the first one? self is still C when this method is defined.
It works similarly to message sends and constant lookup:
The general format of a message send is foo.bar, which sends the message bar to foo. If you leave out foo, the message will be sent to the default receiver (which is self).
The general format of a constant lookup is Foo::Bar, which looks up the constant Bar in the module Foo. If you leave out Foo, the constant will be looked up in the default constant context (or cref).
The general format of a method definition is def foo.bar, which defines the method bar in the singleton class of foo. If you leave out foo, the method will be defined in the default definition context (or default definee):
At the top-level, the default definee is Object. (Also, the methods become private.)
Within a module declaration body, the default definee is self (and not self's singleton class, like you assumed!)
Within a method body, the default definee is the syntactically enclosing module. (Put another way: def doesn't change the default definee.)
instance_eval changes the default definee to the receiver's singleton class
class_eval changes the default definee to the receiver
it's a convention of the ruby language. (conceptually you can think of this like you think about static methods in Java. they are not associated with any instance of the class but with the class itself)
bar is going to be a method on objects instantiated from C.
self.bar is going to be a method on C itself.
What's interesting in Ruby is that C class itself is an object (so the class definition that you can use to build objects is an object itself). That's where the self comes from (i.e. define this on myself vs define this from objects that will be built using me as a blueprint) Read more on this: Ruby craziness: Class vs Object?
I Just started learning ruby and I don't see the difference between an #instace_variable and an attribute declared using attr_accessor.
What is the difference between the following two classes:
class MyClass
#variable1
end
and
class MyClass
attr_accessor :variable1
end
I searched lot of tutorials online and everybody uses different notation, Does it have to do anything with the ruby version? I also searched few old threads in StackOverflow
What is attr_accessor in Ruby?
What's the Difference Between These Two Ruby Class Initialization Definitions?
But still I am not able to figure out what is the best way to use.
An instance variable is not visible outside the object it is in; but when you create an attr_accessor, it creates an instance variable and also makes it visible (and editable) outside the object.
Example with instance variable (not attr_accessor)
class MyClass
def initialize
#greeting = "hello"
end
end
m = MyClass.new
m.greeting #results in the following error:
#NoMethodError: undefined method `greeting' for #<MyClass:0x007f9e5109c058 #greeting="hello">
Example using attr_accessor:
class MyClass
attr_accessor :greeting
def initialize
#greeting = "hello"
end
end
m2 = MyClass.new
m2.greeting = "bonjour" # <-- set the #greeting variable from outside the object
m2.greeting #=> "bonjour" <-- didn't blow up as attr_accessor makes the variable accessible from outside the object
Hope that makes it clear.
Instance variables are not directly visible outside of the class.
class MyClass
def initialize
#message = "Hello"
end
end
msg = MyClass.new
#message
#==> nil # This #message belongs to the global object, not msg
msg.message
#==> NoMethodError: undefined method `message'
msg.#message
#==> SyntaxError: syntax error, unexpected tIVAR
Now, you can always do this:
msg.instance_eval { #message }
or ask for the variable directly like this:
msg.instance_variable_get :#message
But that's awkward and sort of cheating. Poking around someone else's class may be educational, but your client code shouldn't be required to do it to get reliable results. So if you want clients to be able to see those values, don't make them use the above techniques; instead, define a method to expose the value explicitly:
class MyClass
def message
return #message
end
end
msg.message
# ==> "Hello"
Because you so often want to do that, Ruby provides a shortcut to make it easier. The code below has exactly the same result as the code above:
class MyClass
attr_reader :message
end
That's not a new type of variable; it's just a shorthand way to define the method. You can look at msg.methods and see that it now has a message method.
Now, what if you want to allow outsiders to not only see the value of an instance variable, but change it, too? For that, you have to define a different method for assignment, with a = in the name:
class MyClass
def message=(new_value)
#message = new_value
end
end
msg.message = "Good-bye"
msg.message
# ==> "Good-bye"
Note that the assignment operators are semi-magical here; even though there's a space between msg.message and =, Ruby still knows to call the message= method. Combination operators like += and so on will trigger calls to the method as well.
Again, this is a common design, so Ruby provides a shortcut for it, too:
class MyClass
attr_writer :message
end
Now, if you use attr_writer by itself, you get an attribute that can be modified, but not seen. There are some odd use cases where that's what you want, but most of the time, if you are going to let outsiders modify the variable, you want them to be able to read it, too. Rather than having to declare both an attr_reader and an attr_writer, you can declare both at once like so:
class MyClass
attr_accessor :message
end
Again, this is just a shortcut for defining methods that let you get at the instance variable from outside of the class.
attr_accesor gives you methods to read and write the instance variables. Instance variables are deasigned to be hidden from outside world so to communicate with them we should have attr_ibute accesor methods.
In OOPS we have a concept called encapsulation which means, the internal representation of an object is generally hidden from view outside of the object's definition. Only the Object 'itself' can mess around with its own internal state. The outside world cannot.
Every object is usually defined by its state and behavior, in ruby the instance variables is called internal state or state of the object and according to OOPS the state should not be accessed by any other object and doing so we adhere to Encapsulation.
ex: class Foo
def initialize(bar)
#bar = bar
end
end
Above, we have defined a class Foo and in the initialize method we have initialized a instance variable (attribute) or (property). when we create a new ruby object using the new method, which in turn calls the initialize method internally, when the method is run, #bar instance variable is declared and initialized and it will be saved as state of the object.
Every instance variable has its own internal state and unique to the object itself, every method we define in the class will alter the internal state of the object according to the method definition and purpose. here initialize method does the same, such as creating a new instance variable.
var object = Foo.new(1)
#<Foo:0x00000001910cc0 #bar=1>
In the background, ruby has created an instance variable (#bar =1) and stored the value as state of the object inside the object 'object'. we can be able to check it with 'instance_variables' method and that methods returns an array containing all the instance variables of the object according to present state of the object.
object.instance_variables
#[
[0]: #bar
]
we can see '#bar' instance variable above. which is created when we called the initialize method on the object. this '#bar' variable should not be visible (hidden) by default and so it cannot be seen by others from outside of the object except the object, from inside. But, an object can mess around with its own internal state and this means it can show or change the values if we give it a way to do so, these two can be done by creating a new instance methods in the class.
when we want to see the #bar variable by calling it we get an error, as by default we cannot see the state of an object.
show = object.bar
#NoMethodError: undefined method `bar' for #<Foo:0x00000001910cc0 #bar=1>
#from (irb):24
#from /home/.rvm/rubies/ruby-2.0.0-p648/bin/irb:12:in `<main>'
But we can access the variables by two methods, these two are called setter and getter methods, which allow the object to show or change its internal state (instance variables/attributes/properties) respectively.
class Foo
def bar
#bar
end
def bar=(new_bar)
#bar = new_bar
end
end
We have defined a getter(bar) and setter(bar=) methods, we can name them any way but the instance variable inside must the same as instance variable to which we want to show or change the value. setters and getters are a violation to OOPS concepts in a way but they are also very powerful methods.
when we define the two methods by re-opening the class and defining them, when we call the object with the methods, we can be able to view the instance variables(here #foo) and change its value as well.
object.bar
1
object.bar=2
2
object.bar
2
Here we have called the bar method (getter) which returns the value of #bar and then we have called bar= method (setter) which we supplied a new_value as argument and it changes the value of instance variable (#bar) and we can look it again by calling bar method.
In ruby we have a method called attr_accessor , which combines the both setter and getter methods, we define it above the method definitions inside the class. attr_* methods are shortcut to create methods (setter and getter)
class Foo
attr_accessor :bar
end
we have to supply a symbol (:bar) as argument to the attr_accessor method which creates both setter and getter methods internally with the method names as supplied symbol name.
If we need only a getter method, we can call attr_reader :bar
If we need only a setter method, we can call attr_writer :bar
attr_accessor creates both attr_writer and attr_reader methods
we can supply as many instance variables as we want to the attr_* methods seperated by commas
class Foo
attr_writer :bar
attr_reader :bar
attr_accessor :bar, :baz
end
Because attr_accessor defines methods, you can call them from outside the class. A #variable is only accessible from inside the class.
And another answer more compact (for Java developers)
attr_accessor :x creates the getters and setters to #x
class MyClassA
attr_accessor :x
end
is the same as
class MyClassB
def x=(value) #java's typical setX(..)
#x=value
end
def x
#x
end
end