In the description on the left side panel, it says,
"The demo code we're about to show you includes a fancy trick: if you want to end a Ruby statement without going to a new line, you can just type a semicolon. This is a time saver when you're writing something very short, like an empty class or method definition."
Why would we wan to make an empty class? Why wouldn't we just leave it blank?
Thanks for any clarification.
You may want a custom error class that does nothing special except use its name to convey something:
class MySpecialError < Error; end
Or you may want to start by declaring a class and then tack on your functionality later (no problem with that because ruby classes are dynamic):
class Foo; end
def Foo.frobnicate; "something" ; end
Though in ruby, you could just as well do
Foo = Class.new
(The difference is that class Foo; end won't clear an already existing Foo class, whereas with Class.new you're starting from scratch).
Related
I am trying to understand concepts of including or inheriting a module inside a class. Whenever I read i get new ways to include or inherit a module inside a class. So just want to know how many ways are there. Here are the examples I am sharing:
Example 1
module TimeExtensions
refine Fixnum do
def minutes; self * 60; end
end
end
class MyApp
using TimeExtensions
def initialize
p 2.minutes
end
end
Example 2
VAL = 'Global'
module Foo
VAL = 'Foo Local'
class Bar
def value1
VAL
end
end
end
class Foo::Bar
def value2
VAL
end
end
Example 3
module Foo
def foo
puts 'heyyyyoooo!'
end
end
class Bar
include Foo
end
Out of the three, only the last one includes a module into the class. That is, it adds the methods from the module to the class.
The first one is called refinement. If instead of refining Fixnum you just added a #minutes method to it, Fixnum will have that method for everyone that uses it, as long as your code is loaded. This might cause conflicts with other implementations of the same method (for example active record's #minutes) and leads to obscure, hard to debug issues. Instead, you can refine the Fixnum class and it will have that method only in the scope where you added the refinement with using.
It has some issues and it's not very widely used. But for the purposes of this question, the differences between including a module and using a refinement are:
including will add methods to the class where you do the inclusion, while refinements make other classes behave differently in the context where they are used
including is semantical (all objects will have the new included methods), while refinements are lexical (after you close the class, if you reopen it again, you won't see the refined methods)
The second one is scoping the class inside the module. This doesn't add methods anywhere. It is just due to the way constants are searched that if the constant (in this case VAL) isn't found in the current class, it is searched further up the tree. It's not that simple actually, if you want more details, you can read here.
I was thinking wouldn't it be cool to have a print method defined in the Ruby Object class? Consider the following:
class Object
def print
puts self.to_s
end
end
23.times &:print
Is there any issue in having something like this? Seems like a good feature to have. It also appears easy to read.
There's already Object#inspect defined. Plus, there's already Kernel#print defined as private method in Object class and every class that inherits from it.
This method already exists in the Ruby standard library. However, it has a different name: display.
23.times &:display
# 012345678910111213141516171819202122
As you can see, it does not write a newline after the object's string representation; it is ill-suited for object inspection.
The main issue with adding methods to Object is that they become universal and may clash with similarly named methods in other libraries or in your project.
There are already multiple simple ways to output data or convert to string form in Ruby core, so the risk of a clash (on a very useful method name) likely outweighs any benefits from nicer syntax even in your own code.
If you have a smaller set of classes in your own project, where you feel this would be a useful feature to have, then this is an ideal use case for mix-ins.
Define a module:
module CanPrintSelf
def print
puts self.to_s
end
end
And include it in any class you want to have the feature:
class MyClass
include CanPrintSelf
end
my_object = MyClass.new
my_object.print
So you can have this feature if you like it, and you don't need to modify Object.
Is it possible to code something that can tell me when a Ruby class is defined?
Yes!
class Object
def self.inherited(base)
puts "#{base} inherited from object"
end
end
class Animal
end
class Cat < Animal
end
Running the above code prints the following:
Animal inherited from object
Cat inherited from object
Basically, the self.inherited callback is triggered whenever a class is defined that inherits from the class it is defined on. Put it on Object and that's any class! (Although there may be some special case exceptions I can't think of just now).
I should probably add the disclaimer that, while it is possible to do this (because of just how awesome Ruby is as a language), whether it is advisable to do this, especially in code destined for production use, I'm not so sure. Well, actually, I am sure. It would be a bad idea.
Suppose you write a class Sup and I decide to extend it to Sub < Sup. Not only do I need to understand your published interface, but I also need to understand your private fields. Witness this failure:
class Sup
def initialize
#privateField = "from sup"
end
def getX
return #privateField
end
end
class Sub < Sup
def initialize
super()
#privateField = "i really hope Sup does not use this field"
end
end
obj = Sub.new
print obj.getX # prints "i really hope Sup does not use this field"
The question is, what is the right way to tackle this problem? It seems a subclass should be able to use whatever fields it wants without messing up the superclass.
EDIT: The equivalent example in Java returns "from Sup", which is the answer this should produce as well.
Instance variables have nothing to do with inheritance, they are created on first usage, not by some defining mechanism, therefore there is no special access control for them in language and they can not be shadowed.
Not only do I need to understand your
published interface, but I also need
to understand your private fields.
Actually this is an "official" position. Excerpt from "The Ruby Programming Language" book (where Matz is one of the authors):
... this is another reason why it is only safe to extend Ruby
classes when you are familiar with
(and in control of) the implementation
of the superclass.
If you don't know it inside and out you're on your own. Sad but true.
Don't subclass it!
Use composition instead of inheritance.
Edit: Rather than MyObject subclassing ExistingObject, see if my_object having an instance variable referring to existing_object would be more appropriate.
Instance variables belong to instances (ie objects). They're not determined by the classes themselves.
unlike java/C#, in ruby private variables are always visible to the inheriting classes. There is no way to hide the private variables.
Ruby and Java don't treat 'private' property the same way. In Ruby if you mark something as private it only means that it can't be called with receiver, i.e.:
class Sub
private
def foo; end
end
sub.foo => error accessing private method with caller
but you can always access it if you change who is self like:
sub.instance_eval { foo } #instance_eval changes self to receiver, 'sub' in this example
Conclusion: Don't rely that you can hide or protect something from outer space! Or with great power comes great responsibility!
EDIT:
Yes, I know question was for fields but it's the same thing. You can always do:
sub.instance_eval { #my_private_field = 'something else' }
puts sub.instance_eval { #my_private_field }
I have a curiosity question. If I have a ruby class and then I dynamically add class methods, class variables, etc. to it during execution is there anyway for me to save the altered class definition so that next time I start my application I can use it again?
There is no built-in way to do this. Marshal can't save methods. If these methods and variables are generated in some systematic way, you could save the data necessary for the class to recreate them. For example, if you have a make_special_method(purpose, value) method that defines these methods, create an array of the arguments you need to pass to these methods and read it in when you want to reconstitute the state of the class.
Depending on what exactly you mean, there are a couple of ways to go about this.
The simplest case is the one where you've added variables or methods to an already-existing class, as in this example:
class String
def rot13
return self.tr('a-z', 'n-za-m')
end
end
Here we've added the rot13 method to class String. As soon as this code is run, every String everywhere in your program will be able to #rot13. Thus, if you have some code that needs rot13-capable strings, you just ensure that the code above is run before the code in question, e.g. by putting the rot13 code in a file someplace and require()ing it. Very easy!
But maybe you've added a class variable to a class, and you want to preserve not just its existence but its value, as in:
class String
##number_of_tr_calls_made = 0
# Fix up #tr so that it increments ##number_of_tr_calls_made
end
Now if you want to save the value of ##number_of_tr_calls_made, you can do so in the same way you would with any other serializable Ruby value: via the Marshal library. Also easy!
But something in the way you phrased your question makes me suspect that you're doing something like this:
greeting = "Hello"
class <<greeting
def rot13
return self.tr('a-z', 'n-za-m')
end
end
encrypted_greeting = greeting.rot13
This is very different from what we did in the first example. That piece of code gave every String in your program the power to rot13 itself. This code grants that power to only the object referred to by the name 'greeting'. Internally, Ruby does this by creating an anonymous Singleton subclass of String, adding the rot13 method to it, and changing greeting's class to that anonymous subclass.
The problem here is that Singletons can't be Marshal'd (to see why, try to figure out how to maintain the Singleton invariant when any call to Marshal.load can generate copies of extant Singleton objects). Now greeting has a Singleton in its inheritance hierarchy, so if you want to save and load it you are hosed. Make a subclass instead:
class HighlySecurableString < String
def rot13
return self.tr('a-z', 'n-za-m')
end
end
greeting = HighlySecurableString.new("hello")
Simply marshalling the object (as others have said) wont work. Lets look at an example. Consider this class:
class Extras
attr_accessor :contents
def test
puts "This instance of Extras is OK. Contents is: " + #contents.to_s
end
def add_method( name )
self.class.send :define_method, name.to_sym do
puts "Called " + name.to_s
end
end
end
Now lets write a program which creates an instance, adds a method to it and saves it to disk:
require 'extras'
fresh = Extras.new
fresh.contents = 314
fresh.test # outputs "This instance of Extras is OK. Contents is: 314"
fresh.add_method( :foo )
fresh.foo # outputs "Called foo"
serial = Marshal.dump( fresh )
file = File.new "dumpedExample", 'w'
file.write serial
So we can call the normal method 'test' and the dynamic method 'foo'. Lets look at what happens if we write a program which loads the instance of Example which was saved to disk:
require 'extras'
file = File.new 'dumpedExample', 'r'
serial = file.read
reheated = Marshal.load( serial )
reheated.test # outputs "This instance of Extras is OK. Contents is 314"
reheated.foo # throws a NoMethodError exception
So we can see that while the instance (including the values of member variables) was saved the dynamic method was not.
From a design point of view it's probably better to put all your added code into a module and load that into the class again when you next run the program. We'd need a good example of how you might want to use it though to really know this.
If you need extra information to recreate the methods then have the module save these as member variables. Implement included in the module and have it look for these member variables when it is included into the class.
http://ruby-doc.org/core/classes/Marshal.html
You're editing the class on the fly, and you want to save that? You could try using the Marshal module, it'll allow you to save objects to a file, and read them back in memory dynamically.