Better to extend a class or change it directly?

So, I am working on creating a visualization for a data structure in Java. I already have an implementation of the data structure (Binary Search Tree), but I need to add additional functions to the included node class. As for conventions and best practices, should I create a subclass of node with this added functionality, or should I just change what I have and document it there?

My question is similar to what I asked here , but it's a little over my head.

I know that this probably doesn't matter much for what I'm doing, so I ask for more on this.

Edit: I probably should have been more clear. My modifications do not actually change the original implementation, except to add a few additional fields (x and y coordinates plus a boolean to determine if this node is highlighted) and access / change functions for these fields. Also the node class I'm working with is included in the BST implementation

From reading your answers, it seems that arguments should be made for both cases. I agree that creating a separate class or interface is probably best done as a whole. Creating another class seems like it might get complicated, since you still need a way to retrieve data from node. The BST implementation that I use is generic and does not have such functions on its own in the node class or in the BST class to just return the data, so at least I have to add this.

Thanks for the informative answers.

+4
source share
5 answers

The question is, is “core functionality” useful, even undesirable, when you are not visualizing the data structure?

You might not even want to extend the class. Without details, it seems to me that you have a data structure that works. You can create a new class that knows how to render it.

That is, instead of a data structure, than knowing how to visualize yourself, you have a data structure and another class that knows how to visualize a data structure. Heck - you may find that this evolves into a different class hierarchy because you may need to visualize queues, stacks, etc. Etc. DO NOT do ANYTHING with your binary search tree.

+11
source

As you ask in general, here is a short answer: it really depends on the situation .

First, it is assumed that subclasses have an IS-A relationship with their parent classes. If you cannot say that your new subclass IS is a specific kind of source class, you are asking the wrong question and must create a new class that is not associated with it.

  • If the new code is closely related to the main purpose of the class and applies to all members of the class (for example, all BSTs), it is better to change it. High cohesion is good.
  • If your new code is related to the main purpose of the class, but it is associated only with some objects of this type (for example, only with BST, which are balanced), perhaps subclasses are the way to go.
  • Depending on what you change, how many places your code uses, how many different people / organizations use it, and your changes may lead to unexpected behavior in another code, so you should think twice before changing the existing code. This does not mean automatically subclassing commonly used things; which is often wrong for the reasons described above.

In your particular case, I agree with n8wrl; since visualization has nothing to do with data structures, it is probably better to implement a whole separate Visualizable interface than to create a subclass of DrawableBSTNode .

+3
source

I would say that in the general case of adding functionality to an existing implementation, you should extend the existing implementation, not modify it.

And here is my reasoning. If this node is used everywhere except the implementation of binary search, then when you change it, you need to find it wherever it is used to ensure that none of these places conflict with your changes. Although simply adding functionality as new methods usually does not cause problems, it can cause problems. You never know how an object is used.

Secondly, even if it is used only in the binary search tree, you still need to make sure that the BST implementation will work well with your changes.

Finally, if you extend it, you don’t need to worry about points one and two. And you get an additional bonus from the fact that your changes are saved separately from the initial implementation for the whole time. This will make it easier to track your comments and comment on them.

+2
source

There is no simple answer, knowing when and how to add functionality - this is what you should learn over time.

Just adding to the base class seems like a simple solution, but it pollutes your base class. If this is a class that you can reasonably expect from using another program (or even parts of your program), does the functionality you add add to the context of your class responsibility? If not, this is probably a bad move. Are you adding dependencies that link your base class with your specific use? Because if you chose to reuse the code directly from the window.

Inheritance is the solution that many engineers seek, and this is a seductive route. But since I grew up as an engineer, I use it sparingly. Inheritance should only be used in true relationships - and you need to respect behavioral subtyping or are you going to regret it later. And since Java allows only one inheritance, this means that you get only one snapshot when subtyping.

Composition (especially with interfaces) is often the best idea. Often, what looks like an is-a relationship does have one-one. Or sometimes all you really need is a helper class that has many functions that take your original class as an argument.

However, there is one problem with the composition; you want to save these objects in your tree. The solution here is the interfaces. You do not want the tree to store nodes. You want objects that have an interface that node can give you.

 public interface HasNode { public Node getNode(); } 

Your node class is HasNode with getNode just returning this. Your NodeVisualizer class is also HasNode, and now you can also store NodeVisualizers in your tree. Of course, now you have one more problem: your tree may contain NodeVisualizers and nodes, and this will not be good. Plus, when you return HasNode from tree functions, you have to drop them in the right instance and it is ugly. You want to use templates for this, but this is a different answer.

+2
source

Mixing logically independent functions will cause a mess. Subclassification is a very special relationship, often abused. The subclass is for Is-a-Kind relationships.

If you want to visualize something, why not create a completely independent class for this? You can simply pass your Node object to this. (Or even better, use the interface.)

0
source

Source: https://habr.com/ru/post/1308262/


All Articles