Is it conventional to define a subclass under it's parent class like below?
class Element
class Div < Element
end
class Paragraph < Element
end
end
Or is it more appropriate to make a module to contain the subclasses?
class Element
end
module Elements
class Div < Element
end
class Paragraph < Element
end
end
Or to create a "base" class in a module and define the subclasses within the same module?
module Element
class Base
end
class Div < Base
end
class Paragraph < Base
end
end
Or is it better to force a naming convention?
class Element
end
class DivElement < Element
end
class ParagraphElement < Element
end
It seems every library chooses a different namespacing/naming convention.
Which is the best to use?
What are the pros and cons of each?
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass. A nested class has access to all the private members of its enclosing class—both fields and methods.
A class in Java can be declared as a subclass of another class using the extends keyword. A subclass inherits variables and methods from its superclass and can use them as if they were declared within the subclass itself: class Animal { float weight ; ...
No. It makes zero sense to allow that. The reason is because subclasses generally define additional behavior. If you could assign a superclass object to a subclass reference, you would run into problems at runtime when you try to access class members that don't actually exist.
Definition: A subclass is a class that derives from another class. A subclass inherits state and behavior from all of its ancestors. The term superclass refers to a class's direct ancestor as well as all of its ascendant classes.
TL;DR: The most conventional and best way to do this is with a module containing a base class and its subclasses. But let's go over everything.
There aren't many official sources on this; however, it is the style to use modules to contain libraries, code, and groups of classes.
Pros:
Cons:
Having the subclasses in a superclass really depends on situation. However, any benefits of this method are also achieved by the module method. But in practice, this just isn't done. Classes are here to contain methods, instance variables, class methods, etc. But classes can be thought of as a last level of nesting -- you don't have a class in a class unless it's a very specific circumstance.
The one case where I can think of this making sense is a case where the only way subclasses are used is through the superclass, for example a Formatter
class that has internal subclassses like XML
, PDF
, etc. Let's say that you only use these classes by doing things like Formatter.new(:xml)
. But if we're doing this, the subclasses should be private and not accessible to the outside world anyway. And at that point, inheritance is a very C++y way and not Rubyish at all.
Pros:
Cons:
This method is very unnatural. It makes it look as if Element
has nothing to do with it's children, or if looked at differently, that it's children are internal implementation details that aren't to be dealt with. Either way it looks like shabby, sloppy naming and bad code structure planning. If I were reading code using this, I'd have to look at the contents of the Elements
module to see that Element
was subclassed at all -- and this isn't the most natural thing to do.
Pros:
include
ed into any code.Element
and the subclasses. They are obviously a bundle of functionality.Cons:
Base
that are very ambiguous.This is the best approach. It makes the classes a neat bundle, while still showing an obvious association and an obvious "Here, use my Div
class" (as opposed to the subclasses-in-class strategy). Also, this is really helpful for metaprogramming, where having everything in a module is crucial to make things work. Finally, this works well with constructs like autoload
, require_relative
, include
, etc. Those show that this is the way the language was designed to be used.
Pros:
Div
or Para
by turning them into DivElement
and ParaElement
.Cons:
This is a very, VERY bad solution. It encorages writing sloppy, C-style code with little organization and little sense. These kinds of naming conventions should only be used in languages where there is no better solution, and Ruby has plenty of better solutions. Even defining all the classes in an array is better than a naming convention.
Note: However, if you really want to, you can define a naming convention on short names like Div
or Para
as long as you still keep them in a module, so that it's Elements::DivElement
. However, this violates DRY, and I wouldn't suggest it.
So, you really have two options. Just put everything in a module:
module Elements
class Element; end
class Div < Element; end
#etc...
end
Or, put everything in a module with a naming convention:
module Elements
class Element; end
class DivElement < Element; end
#etc...
end
I sugest the former for clarity, use of standard methods, and metaprogramming reasons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With