If I have a class Salad with a method chew and I use super in it, it will call the next available chew method available going up the chain of ancestors. What if I want to "reach two levels up" (to the second available chew method going up the chain)? Is there any way to do that without adding super to the first ancestor's method?
To make this a little more concrete, suppose this is my Salad class, with a salad object:
class Salad < Food
include Almonds
include Gorgonzola
include Spinach
include Dressing
def chew
super
end
end
salad = Salad.new
The array of the ancestors would be like this:
[Salad, Dressing, Spinach, Gorgonzola, Almonds, Food, Object, Kernel, BasicObject]
If I want salad.chew to trigger the chew method in Spinach without adding super to Dressing#chew, is that possible? Is there a way to reach two levels up (in the same way that super "reaches" one level up)?
Yes, there is a way to do what you are describing, and that way is through methods #method and #instance_method, as in method = Spinach.instance_method( :chew ), which you can then bind to Salad, or to metaclasses of Salad instances, as in method.bind( Salad ). This mechanism is not as neat as using the convenience keyword super, but offers a superset of super's functionality. There are a few more details, but trust me, this way, you can do anything you want. That's the power of Ruby – you can do anything, up to the point that for the Lispiest magic, you need Ripper, and (the thus far unfinished) Sorcerer.
(For a usage example, see my other answer at Using the Object.inspect / Object.to_s on a class derived from Hash)
No, there's no way to do what you are describing (and for good reason). Any use of the "super-super" keyword which you describe would be too tightly coupled to the details of your inheritance chain (and which classes/modules in that chain implement a given method). It would be very brittle; if such a keyword existed, and you used it, then small changes like moving a method definition would very easily break things. It would also be very confusing for readers of your code.
The purpose of the super keyword is: you can take a class, subclass it, override a method, and add some new behaviors to that method, while still doing everything that the method originally did. super effectively says: "now perform the default behavior for this method". That works regardless of whether that "default" behavior is defined in the superclass, super-superclass, a module, or anywhere else.
If you are wondering how to achieve calling the chew method on all the modules, there is a better solution that is using composition. Modules are for behavior and if you think about your Salad class, you don't want it to behave like a Spinach or Almonds, you want it to be composed of them. So when you chew a salad you chew each of its components.
Related
If I have the following ruby module which implements a particular interface (apply in this case)
module FooApplier
def apply
foo
end
end
...and all other "Appliers" are classes, not modules, is it misleading to other engineers to pass FooApplier to receivers which expect the applyinterface?
Let's assume the application using FooApplier runs perfectly fine, but let's also assume that some other engineer didn't take the time to pour over every last byte of my code. If they decide to send something like .new to the FooApplier which somehow induces some subtle bug, is the onus on my design, or the engineer for making assumptions and neglecting to read my code?
The way your module is presented here, it won't work as a stand-in for a class. Let's look at a class first:
class BarApplier
def apply
bar
end
end
apply here is an instance method, so callable on instances of BarApplier, i.e. BarApplier.new.apply. This will not be possible for your module.
Unless of course apply was meant to be a class or module method, in which case your question was misleading since it then should be def self.apply.
But to answer the more general question, in a duck-typed language the sent messages are the interface. In my opinion the caller should make no assumptions about other methods being present. In your specific case, if apply is the only method in the "contract", assuming that the same entity also responds to new is invalid in my opinion.
I have a typical OO pattern: one base abstract class (that defines abstract methods) and several classes that implement these abstract methods in class-specific way.
I'm used to write documentation only once in abstract methods and then it automatically propagates to several concrete classes (at least it works the following way in Javadoc, in Scaladoc, in Doxygen), i.e. I don't need to repeat the same description in all concrete classes.
However, I couldn't find how to do such propagation in YARD. I've tried, for example:
# Some description of abstract class.
# #abstract
class AbstractClass
# Some method description.
# #return [Symbol] some return description
# #abstract
def do_something
raise AbstractMethodException.new
end
end
class ConcreteClass < AbstractClass
def do_something
puts "Real implementation here"
return :foo
end
end
What I get:
Code works as expected - i.e. throws AbstractMethodException is called in abstract class, does the job in concrete class
In YARD, AbstractClass is clearly defined as abstract, ConcreteClass is normal
Method description and return type is good in AbstractClass
Method is said to throw AbstractMethodException in AbstractClass
Method has no description at all and generic Object return type in ConcreteClass, there's not a single notice of that an abstract method exists in base class.
What I expect to get:
Method's description and return type are inherited (i.e. copied) to ConcreteClass from info at AbstractClass
Ideally, this method is specified in "inherited" or "implemented" section of ConcreteClass description, with some reference link from ConcreteClass#do_something to AbstractMethod#do_something.
Is it possible to do so?
I think the issue boils down to what you're trying to do. It looks like you're trying to implement an Interface in Ruby, which makes sense if you're coming from Java or .NET, but isn't really how Ruby developers tend to work.
Here is some info about how the typical thought on Interfaces in Ruby: What is java interface equivalent in Ruby?
That said, I understand what you're trying to do. If you don't want your AbstractClass to be implemented directly, but you want to define methods that can be used in a class that behaves like the AbstractClass stipulates (as in Design by Contract), then you probably want to use a Module. Modules work very well for keeping your code DRY, but they don't quite solve your problem related to documenting overridden methods. So, at this point I think you can reconsider how you approach documentation, or at least approach it in a more Ruby-ish way.
Inheritance in Ruby is really (generally speaking from my own experience) only used for a few reasons:
Reusable code and attributes
Default behaviors
Specialization
There are obviously other edge cases, but honestly this is what inheritance tends to be used for in Ruby. That doesn't mean what you're doing won't work or violates some rule, it just isn't typical in Ruby (or most dynamically typed languages). This atypical behavior is probably why YARD (and other Ruby doc generators) doesn't do what you expect. That said, creating an abstract class that only defines the methods that must exist in a subclass really gains you very little from a code perspective. Methods not defined will result in a NoMethodError exception being thrown anyway, and you could programmatically check if an object will respond to a method call (or any message for that matter) from whatever calls the method, using #respond_to?(:some_method) (or other reflective tools for getting meta stuff). It all comes back Ruby's use of Duck Typing.
For pure documentation, why document a method that you don't actually use? You shouldn't really care about the class of the object being sent or received from calling a method, just what those objects respond to. So don't bother creating your AbstractClass in the first place if it adds no real value here. If it contains methods you actually will call directly without overriding, then create a Module, document them there, and run $ yardoc --embed-mixins to include methods (and their descriptions) defined in mixed-in Modules. Otherwise, document methods where you actually implement them, as each implementation should be different (otherwise why re-implement it).
Here is how I would something similar to what you're doing:
# An awesome Module chock-full of reusable code
module Stuff
# A powerful method for doing things with stuff, mostly turning stuff into a Symbol
def do_stuff(thing)
if thing.kind_of?(String)
return thing.to_sym
else
return thing.to_s.to_sym
end
end
end
# Some description of the class
class ConcreteClass
include Stuff
# real (and only implementation)
def do_something
puts "Real implementation here"
return :foo
end
end
an_instance = ConcreteClass.new
an_instance.do_somthing # => :foo
# > Real implementation here
an_instance.do_stuff("bar") # => :bar
Running YARD (with --embed-mixins) will include the methods mixed-in from the Stuff module (along with their descriptions) and you now know that any object including the Stuff module will have the method you expect.
You may also want to look at Ruby Contracts, as it may be closer to what you're looking for to absolutely force methods to accept and return only the types of objects you want, but I'm not sure how that will play with YARD.
Not ideal, but you can still use the (see ParentClass#method) construct (documented here). Not ideal because you have to type this manually for every overriding method.
That being said, I'm no Yard specialist but given its especially customizable architecture, I'd be surprised that there would be no easy way to implement what you need just by extending Yard, somewhere in the Templates department I guess.
Does ruby have something different to other OOP languages (eg: PHP) that makes interfaces useless? Does it have some kind of replacement for this?
Edit:
Some clarifications:
In other languages (eg: PHP), you don't "need" interfaces (they are not mandatory at code level). You use them to make a contract, to improve the architecture of the software. Therefore, the affirmation 'in ruby you don't need interfaces / in other languages you need interfaces because XXX' is false.
No, mixins are not interfaces, they are a complete different thing (PHP 5.4 implements mixins). Have you even used interfaces?
Yes, PHP is OOP. Languages evolve, welcome to the present.
Well, it's a consensus that when an object is passed in Ruby it's not type-checked. Interfaces in Java and PHP are a way to affirm that an object complies to a certain contract or "type" (so something might be Serializable, Authorizable, Sequential and whatever else that you want).
However, in Ruby there is no formalized notion of a contract for which interfaces would fulfill some meaningful role as interface conformance is not checked in method signatures. See, for example, Enumerable. When you mix it into your object you are using its functionality as opposed to declaring that your object is Enumerable. The only benefit of having your object being Enumerable is that having defined each(&blk) you automatically get map, select and friends for free. You can perfectly have an object which implements all of the methods provided by Enumerable but does not mix in the module and it would still work.
For example, for any method in Ruby that expects an IO object you could feed in something that has nothing to do with an IO, and then it would explode with an error or - if you implemented your IO stub correctly - it will work just fine even though your passed object is not declared to be "IO-ish".
The idea behind that comes from the fact that objects in Ruby are not really glorified hash tables with a tag slapped onto them (which then have some extra tags that tell the interpreter or the compiler that this object has interface X therefore it can be used in context Y) but an enclosed entity responding to messages. So if an object responds to a specific message it fullfils the contract, and if it does not respond to that message - well then an error is raised.
So the absence of interfaces is compensated partially by the presence of Modules (which can contain functionality that you reach for without doing any type promises to the caller/consumer) and partially by the tradition of message-passing as opposed to typed dicts.
You should watch some presentations by Jim Weirich since he touches on the subject extensively.
This question is kind of open-ended, but here is my take:
The purpose of an interface declaration is two things:
Declare to your future self or colleagues what methods this class must have
Declare to your computer what methods this class must have
If we take the second purpose first, Ruby source code is never compiled, so there is never an option to verify the conformance to the interface declaration and warn the developer of any failure to conform. This means that if Ruby had some built-in interface support, it wouldn't have an option to verify the conformance until runtime, where the application will crash anyway, because of the missing implementation.
So back to the first purpose. Code readability. This could make sense and a formal Ruby convention of specifying interfaces might be helpful. For now, you would probably communicate this using comments or specs or - as I would probably prefer - a declarative module inclusion. E.g.
module Shippable
# This is an interface module. If your class includes this module, make sure it responds to the following methods
# Returns an integer fixnum representing weight in grams
def weight
raise NotImplementedError.new
end
# Returns an instance of the Dimension class.
def dimensions
raise NotImplementedError.new
end
# Returns true if the entity requires special handling.
def dangerous?
raise NotImplementedError.new
end
# Returns true if the entity is intended for human consumption and thereby must abide by food shipping regulations.
def edible?
raise NotImplementedError.new
end
end
class Product
include Shippable
end
A way of enforcing this interface would be by creating a spec that creates an instance of every class that includes the Shippable module, calls the four methods and expects them to not raise NotImplementedError.
I'm a 'Ruby person', and I would like interfaces, or something like them.
Not to enforce a contract - because enforcing anything isn't very Ruby, and kind of defeats the point of a dynamic language, and anyway there's no "compilation" step to enforce it at - but to document contracts that client subclasses can choose to conform to (or not, although if they choose not to they can't complain if the code doesn't work).
When I'm faced with this problem, ie, when I'm writing a class or module I expect subclasses to provide methods for, I usually document the methods I expect subclasses to provide like this:
module Enumerable
def each
raise NotImplementedError, "Subclasses must provide this method"
end
end
It's not ideal, but it's a reasonably rare case and it works for me.
As ruby is duck-typed, no separate interface is needed, but the objects only need to implement the common methods. Look at the "classic" example below:
class Duck
def move
"I can waddle."
end
end
class Bird
def move
"I can fly."
end
end
animals = []
animals << Duck.new
animals << Bird.new
animals.each do |animal|
puts animal.move
end
In this example, the "interface" is the move method, which is implemented by both the Duck and the Bird class.
I believe it's because Ruby is dynamically typed whereas other languages are statically typed. The only reason you'd need to use an interface in PHP is when you use type hinting when passing objects around.
Ruby is very dynamic and duck-typed. Wouldn't that make interfaces kind of useless or overkill? Interfaces force classes to have certain methods available at compile time.
Review this too:
http://en.wikipedia.org/wiki/Duck_typing
Depends what you mean by interface.
If by interface you mean a concrete object that exists in your language that you inherit from or implement then no you don't use interfaces in a language like ruby.
If you mean interface as in objects have some well documented interface then yes of course, objects still have a well documented interfaces, they have attributes and methods that you expect to be there.
I'd agree that interfaces are something that exists in your mind and the documentation and not in the code as an object.
Is it considered bad practice to reference accessors on the extended object from within a mixin method? A simplistic example:
module WindInstrument
def play
mouthpiece.blow #requires a mouthpiece
end
end
class Saxophone
attr_reader :mouthpiece
def initialize
#mouthpiece = Mouthpiece.new
end
include WindInstrument
end
Saxophone.new.play
In this case, I would actually just move the requirement for a mouthpiece directly to the WindInstrument module, but what about in a more complex scenario, where it really makes sense for the accessor to live on the extended object? Is this just an issue of an inappropriate separation of concerns?
Mixins feel useful for adding encapsulated behavior that doesn't require knowledge of the extended object's state. In fact, my gut tells me that a mixin shouldn't have knowledge of any state, whatsoever. If it needs knowledge of state, I would typically fall back to one of two choices:
Put the state in a class, and add it through composition, instead of through the inheritance hierarchy. My issue with this is that I know rubyists out there are creating mixins that access state, which makes for more readable, if less intuitive (to me) design.
Pass the mouthpiece as a parameter to the module. Even I can tell that this seems to muddy the design, and feels like an abomination in the ruby worldview.
Does this code bother anyone else? I know there are a lot of smart people using ruby out there, so I assume the problem is mine. What am I missing? Do I just need to chill out? What would you do?
I think it's the same as in monkey-patching: it's ok to do it, but you have to make sure that there are no alternatives first (ie. You can't modify the classes using your interface) and second, you must be very explicit about it (make sure that the docs, the comments and the interface mention that this our that method is required and will be invoked) and throw a useful error message if it isn't
Ruby's accessors are interfaces, not implementation.
For example, if you call person.height_in_feet=, you don't know what units the height is actually implemented in as an instance variable. It could be metres, feet, or cubits.
One real-life example of mixins using an accessor is the Enumerable module. Although I don't include this module in any classes I create, I'm happy with what it does. It gives you convenient methods like map and each_with_index, while staying DRY - there's only one implementation of what objects you'd access with all of the methods of the "mixee", and there's only one definition of what map does, for any object that uses Enumerable.
I was reading up on Ruby, and learned about its mixins pattern, but couldn't think of many useful mixin functionality (because I'm not used to thinking that way most likely). So I was wondering what would be good examples of useful Mixin functionality?
Thanks
Edit: A bit of background. I'm Coming from C++, and other Object languages, but my doubt here is that Ruby says it's not inheriting mixins, but I keep seeing mixins as Multiple inheritance, so I fear I'm trying to categorize them too soon into my comfort zone, and not really grok what a mixin is.
They are usually used to add some form of standard functionality to a class, without having to redefine it all. You can probably think of them a bit like interfaces in Java, but instead of just defining a list of methods that need to be implemented, many of them will actually be implemented by including the module.
There are a few examples in the standard library:
Singleton - A module that can be mixed into any class to make it a singleton. The initialize method is made private, and an instance method added, which ensures that there is only ever one instance of that class in your application.
Comparable - If you include this module in a class, defining the <=> method, which compares the current instance with another object and says which is greater, is enough to provide <, <=, ==, >=, >, and between? methods.
Enumerable - By mixing in this module, and defining an each method, you get support for all the other related methods such as collect, inject, select, and reject. If it's also got the <=> method, then it will also support sort, min, and max.
DataMapper is also an interesting example of what can be done with a simple include statement, taking a standard class, and adding the ability to persist it to a data store.
Well the usual example I think is Persistence
module Persistence
def load sFileName
puts "load code to read #{sFileName} contents into my_data"
end
def save sFileName
puts "Uber code to persist #{#my_data} to #{sFileName}"
end
end
class BrandNewClass
include Persistence
attr :my_data
def data=(someData)
#my_data = someData
end
end
b = BrandNewClass.new
b.data = "My pwd"
b.save "MyFile.secret"
b.load "MyFile.secret"
Imagine the module is written by a Ruby ninja, which persists the state of your class to a file.
Now suppose I write a brand new class, I can reuse the functionality of persistence by mixing it in by saying include ModuleILike. You can even include modules at runtime. I get load and save methods for free by just mixing it in. These methods are just like the ones that you wrote yourself for your class. Code/Behavior/Functionality-reuse without inheritance!
So what you're doing is including methods to the method table for your class (not literally correct but close).
In ruby, the reason that Mixins aren't multiple-inheritance is that combining mixin methods is a one time thing. This wouldn't be such a big issue, except that Ruby's modules and classes are open to modification. This means that if you mixin a module to your class, then add a method to the module, the method will not be available to your class; where if you did it in the opposite order, it would.
It's like ordering an ice-cream cone. If you get chocolate sprinkles and toffee bits as your mixins, and walk away with your cone, what kind of ice cream cone you have won't change if someone adds multicolored sprinkles to the chocolate sprinkles bin back at the ice-cream shop. Your class, the ice cream cone, isn't modified when the mixin module, the bin of sprinkles is. The next person to use that mixin module will see the changes.
When you include a module in ruby, it calls Module#append_features on that module, which add a copy of that module's methods to the includer one time.
Multiple inheritance, as I understand it, is more like delegation. If your class doesn't know how to do something, it asks its parents. In an open-class environment, a class's parents may have been modified after the class was created.
It's like a RL parent-child relationship. Your mother might have learned how to juggle after you were born, but if someone asks you to juggle and you ask her to either: show you how (copy it when you need it) or do it for you (pure delegation), then she'll be able at that point, even though you were created before her ability to juggle was.
It's possible that you could modify a ruby module 'include' to act more like multiple inheritance by modifying Module#append_features to keep a list of includers, and then to update them using the method_added callback, but this would be a big shift from standard Ruby, and could cause major issues when working with others code. You might be better creating a Module#inherit method that called include and handled delegation as well.
As for a real world example, Enumerable is awesome. If you define #each and include Enumerable in your class, then that gives you access to a whole host of iterators, without you having to code each and every one.
It is largely used as one might use multiple inheritance in C++ or implementing interfaces in Java/C#. I'm not sure where your experience lies, but if you have done those things before, mixins are how you would do them in Ruby. It's a systemized way of injecting functionality into classes.