The two invocations of an instance method carry different semantics. The first call to bar works as expected.
class T
def foo
bar # <= This works. "bar" is printed.
self.bar # <= EXCEPTION: `foo': private method `bar' called for ...
end
private
def bar
puts 'bar'
end
end
t = T.new
t.foo
I'd like to understand why. What causes self.bar to have a different semantics, throwing an exception? I'm not interested in the exception per se since I can work around with the dubious removal of the private label, but primarily interested in the semantic discussion.
Private methods can not be called with explicit receiver like self. This means that you can call a private method from within a class it is declared in as well as all subclasses of this class.
Here is a good article about that. It explains well why code like yours will raise NoMethodError.
On wikibooks there is also a good explanation of visibility levels in ruby.
For the reference you can bypass this with Object#send but generally it is considered as a bad practice to do so.
Related
I sometimes use this construct:
class Test
def today
date = Date.today
def date.is_friday?
strftime("%A") == "Friday"
end
date
end
end
it works fine...
t = Test.new
t.today # => <Date: 2016-09-03 ((2457635j,0s,0n),+0s,2299161j)>
t.today.is_friday? # => false
I have always thought of this as a nested method. But others are adamant that Ruby does not have nested methods. OK, I'm not hooked on the name. But what DO you call it? And is there a better way to achieve the same functionality?
When people talk about nested methods/functions, they generally mean things that are only visible/usable from within the enclosing method. This isn't true of your example - once defined, it can be called on that object by anyone.
What you're showing is Ruby's singleton methods: the ability to define a method on one instance of a class (for example when people say class method in ruby, those are actually singleton methods on that instance of the Class class)
As to whether there is a better way, that is unanswerable since you haven't said what the problem you are trying to solve is.
Calling def inside a method is usually the wrong way to do this. What you want is to define a module that encapsulates this and potentially other methods, then mix that in on any objects as necessary:
module DateExtensions
def is_friday?
wday == 5
end
end
It's worth noting that strftime might return values other than "Friday" because localization may be in effect. You could get "Freitag" or "Vendredi" depending on where you are. The wday method returns a predictable numerical value.
Now you can mix this in:
class Test
def today
date = Date.today
date.extend(DateExtensions)
date
end
end
By declaring these methods inside a module it's a lot more obvious they're part of a package. It also means you don't need to define a brand new method for each instance of a Date you create.
A more Ruby way of doing this is to define your own subclass of Date that adds in this additional behaviour.
Method definitions are code just like any other code. They can appear in methods just like any other code. And just like any other code, they will be executed every time the method runs.
So, this
class Foo
def foo
def bar
end
end
end
is not a nested method, but simply a method that defines a method. It is easy to see that this is not a nested method, by simply calling it twice, paying attention to the warnings generated and inspecting the defined methods of the surrounding module:
foo = Foo.new
Foo.public_instance_methods(false)
#=> [:foo]
foo.foo
Foo.public_instance_methods(false)
#=> [:foo, :bar]
foo.foo
# (irb):3: warning: method redefined; discarding old bar
# (irb):3: warning: previous definition of bar was here
As you can see, bar is not nested inside foo, instead it is defined besides foo in class Foo. It is only defined after foo has run, and it gets re-defined every time foo runs.
Your example is a bit different, of course, since it doesn't keep overwriting the method in the same class, instead it defines it in a different class every time it is called.
Note that there are plans of forbidding this kind of usage, see Feature #11665: Support nested functions for better code organization.
But what DO you call it?
It's a method that defines a method.
And is there a better way to achieve the same functionality?
It's kinda hard to tell what exactly it is you are trying to achieve.
You could create a module with your method and extend all the objects with it. That would be the closest analog.
Other solutions would require a larger restructuring of your code, e.g. using the Decorator Design Pattern or, in your specific Rails use case, a Presenter.
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.
Learning ruby and oop in general, I came upon class methods which as far as I understand are like instance methods but are accessed from the class rather than from an object and can have only one running at the same time.
However, I don't understand why you would use a class method versuses a normal method (outside a class) and what is even their use?
For example:
#Why would you use:
class Foo
def self.bar
puts "Class method"
end
end
#Versus simply:
def bar
puts "Normal method"
end
Foo.bar # => Class method
bar # => Normal method
As they both produce the same result?
I'm quite confused about them so please correct if I'm misunderstanding any/everything here.
Your example isn't a good one.
Class methods might deal with managing all instances that exist of a class, and instance methods deal with a single instance at a time.
class Book
def self.all_by_author(author)
# made up database call
database.find_all(:books, where: { author: author }).map do |book_data|
new book_data # Same as: Book.new(book_data)
end
end
def title
#title
end
end
books = Book.all_by_author('Jules Vern')
books[0].title #=> 'Journey to the Center of the Earth'
In this example we have a class named Book. It has a class method all_by_author. It queries some pretend database and returns an array of Book instances. The instance method title fetches the title of a single Book instance.
So the class method managing a collection of instances, and the instance method manages just that instance.
In general, if a method would operate on a group of instances, or is code related to that class but does not directly read or update a single instance, then it probably should be a class method.
This is more an OOP question than a ruby one. Class methods in ruby are used the same as in other OO programming languages. This means:
class methods are run in the context of a class (and have access only to class variables)
instance methods are run in the context of an object (and have access to object's or instance variables)
Here is a better example:
class Foo
def self.bar
puts 'class method'
end
def baz
puts 'instance method'
end
end
Foo.bar # => "class method"
Foo.baz # => NoMethodError: undefined method ‘baz’ for Foo:Class
Foo.new.baz # => instance method
Foo.new.bar # => NoMethodError: undefined method ‘bar
Here you can see that class method is accessed through a class, while instance method is accessed through an instance or object of a class (Foo.new).
Example is copied from here, where you can also find more information on this subject.
Keep in mind: although any code can be put into a class or a instance method, each has it's own use cases and own pros and contras. In OOP we strive for reusable, flexible and readable code, which means that we usually want to put most of the code as structured as instance methods in a sensible domain model.
Just as you said, they are:
"accessed from the class rather than from an object and"
"can have only one running at the same time."
remember, too, that the class is portable
The most important thing is that it keeps your code organized. When you have hundreds of thousands of lines of code, having them all haphazardly throwing stuff around in the same namespace can become a nightmare. Organization is really important, and namespaces are an easy way to get modularity with support from the language.
Somewhat less importantly, class/module methods can share state without leaking it all over the place (e.g. classes can have instance variables), and they can have private support methods to allow for better factoring, while global methods can't effectively be made private.
You have lots of misunderstanding,
In ruby, we can define class and instance method.
Class method is used to do provide processing at class level i.e. data which can only be available at class level or related to all the objects. For example, to count the number of objects belongs to class you need class method. Like
Foo.count
In same way, to process single object you need object method to process a single object like,
obj.save
So, class method is example of singletone design pattern where object can have there own implementation of same method.
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.
In Ruby, super is a keyword rather than a method.
Why was it designed this way?
Ruby's design tends toward implementing as much as possible as methods; keywords are usually reserved for language features that have their own grammar rules. super, however, looks and acts like a method call.
(I know it would be cumbersome to implement super in pure Ruby, since it would have to parse the method name out of caller, or use a trace_func. This alone wouldn't prevent it from being a method, because plenty of Kernel's methods are not implemented in pure Ruby.)
It behaves a little differently, in that if you don't pass arguments, all of the current arguments (and block, if present) are passed along... I'm not sure how that would work as a method.
To give a rather contrived example:
class A
def example(a, b, c)
yield whatever(a, b) + c
end
end
class B < A
def example(a, b, c)
super * 2
end
end
I did not need to handle the yield, or pass the arguments to super. In the cases where you specifically want to pass different arguments, then it behaves more like a method call. If you want to pass no arguments at all, you must pass empty parentheses (super()).
It simply doesn't have quite the same behaviour as a method call.
super doesn't automatically call the parent class's method. If you imagine the inheritance hierarchy of a ruby class as a list, with the class at the bottom and Object at the top, when ruby sees the the super keyword, rather than just check the the parent class, it moves up the entire list until it finds the first item that has a method defined with that name.
I'm careful to say item because it could also be a module. When you include a module in to a class, it is wrapped in an anonymous superclass and put above your class in the list I talked about before, so that means if you had a method defined for your class that was also defined in the module, then calling super from the class's implementation would call the module's implementation, and not the parent class's:
class Foo
def f
puts "Foo"
end
end
module Bar
def f
puts "Bar"
super
end
end
class Foobar < Foo
include Bar
def f
puts "Foobar"
super
end
end
foobar = Foobar.new
foobar.f
# =>
# Foobar
# Bar
# Foo
And I don't believe that it is possible to access this 'inheritance list' from the ruby environment itself, which would mean this functionality would not be available (However useful it is; I'm not every sure if this was an intended feature.)
Hm, good qustion. I'm not sure how else (besides using super) you would you reference the super version of a given method.
You can't simply call the method by name, because the way that polymorphism works (how it figures out which version of that method to actually call, based on the object class) would cause your method to call itself, spinning into an infinite set of calls, and resulting in a stack overflow.