Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

ruby

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?

like image 524
RyanScottLewis Avatar asked Feb 19 '13 21:02

RyanScottLewis


People also ask

Can a subclass access everything from parent class?

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.

Can a class be its own subclass?

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 ; ...

Can we assign the parent class object to the subclass as a reference?

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.

How do you define subclass?

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.


1 Answers

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 includeed 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.

like image 143
Linuxios Avatar answered Sep 18 '22 12:09

Linuxios