Is it unconventional to define a subclass within it's parent class?

ruby

Solution

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.

Subclasses in Superclass

Pros:

- Self-contained: The entire class system is contained under one name

Cons:

- Unnatural: Who would think to look inside a superclass for a subclass?

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.

Base class outside module, subclasses within

Pros:

- I can't think of any

Cons:

- Implies Non-conected: If Element is not in the same namespace as its children, what, beyond the name tells me that it's even related?

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.

Class and subclasses in module (best solution)

Pros:

- Contained: The superclass and all the Element classes are contained in one namespace, allowing them to be easily imported, required, iterated, etc. Also assists metaprogramming.

- Includable: The classes can be easily `include`ed into any code.

- Clear: There is an obvious association between `Element` and the subclasses. They are obviously a bundle of functionality.

Cons:

- Encourages lazy naming: This does encourage you to name classes things like `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.

Force a naming convention

Pros:

- Simple: No complexity here.

- Removes ambiguity: Removes ambiguity from short names like `Div` or `Para` by turning them into `DivElement` and `ParaElement`.

Cons:

- Archaic: Naming conventions to group classes or methods should only exist in languages that don't have a better way to do it, like C or Objective-C. C++ dropped it as soon as it got namespaces.

- No programatic grouping: These naming conventions, while clear to humans, make the class structure very cloudy to metaprograming code, and make it impossible for the program to deal with the classes as a group

- Pollutes global namespace: This creates many, many names in the global namespace, which is always a bad idea.

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.

Conclusion

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.

Problem

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?

Original source