Include/extend vs class inheritance
In the example given for using a formatter in both a resume and a cv, is there a particular reason that you would write that as a module rather than including them as methods of class ProfessionalDocuments that both Resume and CV can inherit from? My initial thought is it is more preference. Are there examples where doing this as a superclass would be a poor choice, or wouldn't work? What instances would you prefer to do inheritance over include/extend?
Patrick MetcalfePro Student 7,563 Points
So from breaking down your question, I think your problems revolve around the idea of a module.
A module is different from a class in that it can't be instantiated, so having objects thats don't really change make great modules. This example really helped me: I live, and go to school in Chicago, IL, but last year I went to Chile for the summer. Though I speak spanish, the class I did best in Chile was Math. Why? Because believe it or not sin(30 deg) is the same in Chicago and Santiago. So an object that handles math stuff makes a really great module because no matter where you are in your code, Math.sin(30) will give you the same answer. Now imagine if I had a Person class. Your name is Garrett and mine is Patrick so depending on where we are #name will give a different result, making Person a great class.
Math.sin 30.degrees # => 0.5 # Inside a method deep in codebase Math.sin 30.degrees # => 0.5 # Same Same patrick = Person.new "Patrick Metcalfe" garrett = Person.new "Garrett Kocher" patrick.name # => Patrick Metcalfe garrett.name # => Garrett Kocher
So to answer your question Formatter should work the same no matter where its used–inside a CV class or a Resume class, a FormattedPaper class or even a Person class for some reason. Its like math in Chicago and Chile, it works the same no matter where it is, and thus a module is the best choice. If it were a class, it wouldn't make any sense for Resume and CV to inherit from it. Resume is not a Formatter or a FormattedAttributes, it just uses those functionality. Like how a "Playable Player" is a player who can play(format) but is not a Playable (that makes no sense, its an attribute not a noun). Now theoretically you could do the following:
class FormattedDocument extend 'FormattedAttributes' include 'Formatter' end class Resume < FormattedDocument; end class CV < FormattedDocument; end
That would be fine, if thats what you meant, but I interpreted your question differently so lmk if that answers your question or not.
David Gross19,443 Points
You could do that and it would work pretty much the same, except you would have to repeat the method process in two different classes. Since you have two classes that are very similar in attributes you can use NameSpacing. Namespacing is a way of bundling logically related objects together. Using Modules are great for this.
What this example was showing is that you can use NameSpacing in the Module to make your code DRY so you do not have to repeat yourself as much.
remember Include makes the method available to an instance of a class. Extend makes the method available to the class itself.