Something that I see in a lot of code:
class Foo
attr_accessor :bar
# lots of code omitted
def baz
'qux' if bar
end
end
The exact form of the baz method is not too important - it's just that bar here is a reference to the getter method for the instance variable #bar, called from within the instance's class. I would favor retrieving the value from #bar explicitly. Are there any opinions on this?
I've never seen anything in the ruby style guide or similar covering this. I personally find that doing the former makes it harder to read and understand, especially when classes are over several hundred lines long.
Edit:
Perhaps to illustrate what I would consider to be the awkwardness of this design, let's re-evaluate a pretty standard initialize method:
class Foo
attr_accessor :bar, :qux
def initialize(bar, qux)
#bar = bar
#qux = qux
end
end
If we use the setter method, we cannot use bar = ? by analogy. Instead, we have:
class Foo
attr_accessor :bar, :qux
def initialize(bar, qux)
self.bar = bar
self.qux = qux
end
end
which has lost some of the elegance of the first. We have a more flexible design in that we are now free to rewrite our setter method and do away with attr_writer. But I've just some points in style, and it feels a lot like configuration over convention rather than the converse, something that Russ Olsen has declared a design 'pattern' not just of Rails but of Ruby too.
Accessing the attribute through the getter has the advantage of providing encapsulation. The use of an instance variable to store the value is an implementation detail in some respects. Whether that's appropriate is, of course, situational. I don't recall reading anything explicit this style issue, however.
Found https://softwareengineering.stackexchange.com/questions/181567/should-the-methods-of-a-class-call-its-own-getters-and-setters, which discusses the issue from a language-independent point of view. Also found https://www.ruby-forum.com/topic/141107, which is ruby-specific, although it doesn't break any new ground, let alone imply a Ruby standard.
Update: Just came across the following statement on page 24 of http://www.amazon.com/Practical-Object-Oriented-Design-Ruby-Addison-Wesley/dp/0321721330/ref=sr_1_1?s=books&ie=UTF8&qid=1376760915&sr=1-1, a well-respected book on Ruby: "Hide the variables, even from the class that defines them, by wrapping them in methods." (emphasis added). It goes on to give examples of methods in the class using the accessor methods for access.
I would favor retrieving the value from #bar explicitly. Are there any
opinions on this?
Yes, direct access is not as flexible of a design. Getters and setters can be used to transform values. That is why java programmers spend half their lives banging out do nothing setters and getters for their private variables--they want to present the setters and getters as their api, which allows them to change their code in the future to transform values on the way in or the way out without changing the api.
Then ruby came along with the neat attr_accessor method, which meant that writing do nothing setters and getters wasn't painful anymore.
Python goes one step further. In python, instance variables are public and you can directly access them, e.g.
print my_dog.age
A java programmer writing a python program would implement get_age() and set_age() methods:
class Dog:
def get_age(self):
return self.age
def set_age(self, age):
self.age = age
The java programmer would then fly over all the towns in the land and drop leaflets describing the getter and setter methods as the api for getting and setting the age instance variable, and they would warn people not to access the instance variables directly--or else things might break.
However, python has a feature that allows programmers to eliminate getters and setters until they are actually needed to do something useful--rather than dumbly getting or setting a value. Python allows you to transform direct access to instance variables by client code into method calls. To the client it's transparent. For instance, the client code may be accessing an instance variable in a class by writing:
my_dog.age
Python allows the writer of the class to subsequently implement a method named age(), and my_dog.age can be made to call that method instead of directly accessing the instance variable (note that in python, unlike in ruby, you can't normally call a method without the parentheses). The newly implemented age() method can then do anything it wants to the age instance variable before returning it to the client code, e.g. transform it into human years, or retrieve the age from a database.
It's actually faster to use a getter, mainly because attr_reader and attr_accessor are written in C instead of Ruby.
As someone who's been coding Ruby for a few years, I think using attr_* is much more readable. But that's probably just something I've gotten used to.
Related
Coming from C# world I am used to thinking classes are immutable definitions of objects and that every object has fixed class.
I am trying to open my mind to possibilities of using
class << some_object
def something_unique_to_this_object
# code
end
end
I am not talking about class << self.
I am talking about changing one or several object's class definition, but not all of them like class << self does.
In several months or almost a year of using ruby I have never found a situation when I thought oh good I can open this objects eigenclass and change it and leave majority of other objects of same class unchanged. Please provide real world examples when you used this.
You say "not like class << self". Well, guess what - class/module methods are implemented exactly this way. There is a reason for the similarity in syntax. self inside a class definition refers to the class itself. Any class/module methods that you define are actually methods of the eigenclass of that class/module. Your specific class is just one instance of the class Class.
For other examples, look at something like rspec. How would you implement a double and add some methods to it dynamically? How would you stub a method of an existing object? Eingenclasses are an easy and perfect fit for it.
Other than more meta uses, I also sometimes find it comfortable while debugging. Like I can put a breakpoint, alter the behaviour of some object and continue after the breakpoint to see what happens. You might not want to affect all objects of that class or the object might be an instance of an anonymous class.
Currently reading a Ruby style guide and I came across an example:
def no_op; end
What is the purpose of empty body methods?
There are a number of reasons you might create an empty method:
Stub a method that you will fill in later.
Stub a method that a descendant class will override.
Ensure a class or object will #respond_to? a method without necessarily doing anything other than returning nil.
Undefine an inherited method's behavior while still allowing it to #respond_to? the message, as opposed to using undef foo on public methods and surprising callers.
There are possibly other reasons, too, but those are the ones that leapt to mind. Your mileage may vary.
There may be several reasons.
One case is when a class is expected to implement a specific interface (virtually speaking, given that in Ruby there are no interfaces), but in that specific class that method would not make sense. In this case, the method is left for consistency.
class Foo
def say
"foo"
end
end
class Bar
def say
"bar"
end
end
class Null
def say
end
end
In other cases, it is left as a temporary placeholder or reminder.
There are also cases where the method is left blank on purpose, as a hook for developers using that library. The method it is called somewhere at runtime, and developers using that library can override the blank method in order to execute some custom callback. This approach was used in the past by some Rails libraries.
This is not specific to Ruby, but I happen to be using Ruby at the moment.
Here is a class that provides text printing functionality.
class Printer
# some static methods
def self.fancy_print(text)
# do fancy formatting
end
def self.print(text)
fancy_print(text)
end
# some instance methods
def initialize(text)
#text = text
end
def print
#somehow call fancy_print(#text)
end
end
Is it bad design to provide both instance and static methods in a class?
Sometimes I would like to keep several instances of Printer lying around. Other times, I just need to say Printer.print(text) and just grab that text without bothering to store it for later, hence resulting in a static print method and an instance print method.
No, it's not bad design.
It's completely normal–some methods are class methods, some are instance methods. I'm not sure what the perceived issue might even be. It's somewhat difficult to even find classes with only one or the other, although in Java you frequently see static utility classes.
Edit IMO the question is misleading; you're actually asking if it's bad design to have static and instance methods of the same name.
It's tricky if both are public because it isn't necessarily obvious how to use the class. In other words, is it designed to be used via the static, or instance method? Both? What's different about them? Should that difference be... differentiated by a name?
Ultimately it depends on context and usage–there's no single answer.
That's okay, I think. Here's how you would code the Printer#print method
class Printer
def print
self.class.fancy_print(#text)
end
end
There is nothing wrong with having class methods and instance methods for a specific class, as long as they make sense belonging to the class.
I.e. what does fancy_print do? Is it something specific to the Printer class. If it is, then you shouldn't worry.
On the other hand, if it is to be used for any string value, you can do something cheekier, i.e. adding this method to the string class
String.class_eval do
def fancy_print
## implementation
end
end
Now you can do "Hello".fancy_print
Hope this answer was of any use. Also write test cases!
I am studying the ruby object model and have some questions. I understand the idea that an object only stores instance variables, and methods are stored in the class, which an object has a reference to. I also understand the idea of 'self' -- what it is, how it changes, etc.
However, what I don't understand is the notion that 'classes are objects.' Is there a good, intuitive explanation anywhere?
(BTW: I'm using Ruby Object Model and Metaprogramming and Metaprogramming Ruby as my two resources. If anybody can suggest something else, that would be helpful.)
Thanks.
It means precisely what it sounds like — classes are objects. Specifically, they are instances of the class Class, which is itself a subclass of the class Module, which in turn is a subclass of Object, just like every other class in Ruby. Like any other object in Ruby, a class can respond to messages, have its own instance variables, etc.
As a practical example, let's take private.
class Person
attr_accessor :name, :height
private
attr_accessor :weight
end
This gives instances of Person public methods to access the person's name and height, but the accessors for the person's weight are private. BUTBUTBUT — rather than being a keyword like in most languages, private is an ordinary method of the Module class. If we wanted, we could redefine it to do something different for a particular class hierarchy.
class RichardStallman
def self.private(*args)
puts "NO! INFORMATION WAS MEANT TO BE FREE!"
end
end
Here's my shot at one.
In Ruby, classes are objects. Usually they have class Class. For example, let's consider the class Foo.
class Foo
end
Doubtless you've seen this before, and it's not terribly exciting. But we could also have defined Foo this way:
Foo = Class.new
Just as you'd create a new Foo by calling Foo.new, you can create a new Class by calling Class.new. Then you give that class the name Foo by assigning it, just like any other variable. That's all there is to it.
The notion of "classes are objects" ( as I understand it ) implies that anything you can do with an object, you can do it with a class.
This differs from other programming languages where the class and the class definition are special artifacts different from objects and often unaccessible to the runtime.
For instance in Ruby, you can modify any object at runtime, since classes are also objects you can modify the class it self and add methods at runtime, delete methods, or add and delete attributes at runtime.
For instance:
$ irb
>> x = Object.new
=> #<Object:0x1011ce560>
>> x.to_s
=> "#<Object:0x1011ce560>"
>> undef to_s
=> nil
>> x.to_s
NoMethodError: undefined method `to_s' for #<Object:0x1011ce560>
from (irb):4
>>
That's not possible on other programming languages where a distinction between objects and classes is made.
note: Probably you should understand basic Ruby concepts before going to meta programming as it may be confusing, that what I would do.
Look at this article, you may find it helpful:
The Ruby Object Model - Structure and Semantics
Personally I learned a lot about the Ruby object model by reading about the Smalltalk one (e.g. in the Squeak documentation). And depending on how fluent you are in C, the MRI sources are quite approachable and yield the most definite answers.
When you think of it, it's completely logical for new to be a function, right? A function which creates and returns a new object. (Unlike most of other languages where new is some kind of operator or a language construct.)
Pushing it further, even more logical for this function new is that it should be a method, if we are talking about an OO language. Whose method? A method of an object, just a little bit different sort of an object that we can call "class".
So, looking it that way, classes are just special kinds of objects, objects that, among other peculiarities, have method new and know how to create other objects based on their own image.
what I don't understand is the notion that 'classes are objects.' Is there a good, intuitive explanation anywhere?
An answer to SO thread `Visual representation of Ruby Object Model' links to an excellent video on the subject.
Is there any way to make instance variables "private"(C++ or Java definition) in ruby? In other words I want following code to result in an error.
class Base
def initialize()
#x = 10
end
end
class Derived < Base
def x
#x = 20
end
end
d = Derived.new
Like most things in Ruby, instance variables aren't truly "private" and can be accessed by anyone with d.instance_variable_get :#x.
Unlike in Java/C++, though, instance variables in Ruby are always private. They are never part of the public API like methods are, since they can only be accessed with that verbose getter. So if there's any sanity in your API, you don't have to worry about someone abusing your instance variables, since they'll be using the methods instead. (Of course, if someone wants to go wild and access private methods or instance variables, there isn’t a way to stop them.)
The only concern is if someone accidentally overwrites an instance variable when they extend your class. That can be avoided by using unlikely names, perhaps calling it #base_x in your example.
Never use instance variables directly. Only ever use accessors. You can define the reader as public and the writer private by:
class Foo
attr_reader :bar
private
attr_writer :bar
end
However, keep in mind that private and protected do not mean what you think they mean. Public methods can be called against any receiver: named, self, or implicit (x.baz, self.baz, or baz). Protected methods may only be called with a receiver of self or implicitly (self.baz, baz). Private methods may only be called with an implicit receiver (baz).
Long story short, you're approaching the problem from a non-Ruby point of view. Always use accessors instead of instance variables. Use public/protected/private to document your intent, and assume consumers of your API are responsible adults.
It is possible (but inadvisable) to do exactly what you are asking.
There are two different elements of the desired behavior. The first is storing x in a read-only value, and the second is protecting the getter from being altered in subclasses.
Read-only value
It is possible in Ruby to store read-only values at initialization time. To do this, we use the closure behavior of Ruby blocks.
class Foo
def initialize (x)
define_singleton_method(:x) { x }
end
end
The initial value of x is now locked up inside the block we used to define the getter #x and can never be accessed except by calling foo.x, and it can never be altered.
foo = Foo.new(2)
foo.x # => 2
foo.instance_variable_get(:#x) # => nil
Note that it is not stored as the instance variable #x, yet it is still available via the getter we created using define_singleton_method.
Protecting the getter
In Ruby, almost any method of any class can be overwritten at runtime. There is a way to prevent this using the method_added hook.
class Foo
def self.method_added (name)
raise(NameError, "cannot change x getter") if name == :x
end
end
class Bar < Foo
def x
20
end
end
# => NameError: cannot change x getter
This is a very heavy-handed method of protecting the getter.
It requires that we add each protected getter to the method_added hook individually, and even then, you will need to add another level of method_added protection to Foo and its subclasses to prevent a coder from overwriting the method_added method itself.
Better to come to terms with the fact that code replacement at runtime is a fact of life when using Ruby.
Unlike methods having different levels of visibility, Ruby instance variables are always private (from outside of objects). However, inside objects instance variables are always accessible, either from parent, child class, or included modules.
Since there probably is no way to alter how Ruby access #x, I don't think you could have any control over it. Writing #x would just directly pick that instance variable, and since Ruby doesn't provide visibility control over variables, live with it I guess.
As #marcgg says, if you don't want derived classes to touch your instance variables, don't use it at all or find a clever way to hide it from seeing by derived classes.
It isn't possible to do what you want, because instance variables aren't defined by the class, but by the object.
If you use composition rather than inheritance, then you won't have to worry about overwriting instance variables.
If you want protection against accidental modification. I think attr_accessor can be a good fit.
class Data
attr_accessor :id
private :id
end
That will disable writing of id but would be readable. You can however use public attr_reader and private attr_writer syntax as well. Like so:
class Data
attr_reader :id
private
attr_writer :id
end
I know this is old, but I ran into a case where I didn't as much want to prevent access to #x, I did want to exclude it from any methods that use reflection for serialization. Specifically I use YAML::dump often for debug purposes, and in my case #x was of class Class, which YAML::dump refuses to dump.
In this case I had considered several options
Addressing this just for yaml by redefining "to_yaml_properties"
def to_yaml_properties
super-["#x"]
end
but this would have worked just for yaml and if other dumpers (to_xml ?) would not be happy
Addressing for all reflection users by redefining "instance_variables"
def instance_variables
super-["#x"]
end
Also, I found this in one of my searches, but have not tested it as the above seem simpler for my needs
So while these may not be exactly what the OP said he needed, if others find this posting while looking for the variable to be excluded from listing, rather than access - then these options may be of value.