6

I have these instance methods in my Java implementation of Binary Tree and Search Binary Tree: getSize(), getHeight(), getDepth(), getPreOrder(), getInOrder(), getPostOrder() and getLevelOrder(). These methods use the root of the tree in others recursive methods that have a parameter Node. Which is more appropiate to use from the point of view of the OOP:

  1. Using these recursive methods as static methods, because they use an object (Node) that doesn't belong to the actual class, and they don't use any class attributes,
  2. They can be instance methods because they can use in a subtree of this tree and they don't use any static attributes,
  3. or they may be in other static class like UtilsTree()?
RobinHood
  • 377
  • 4
  • 20

3 Answers3

3

From an OOP perspective I believe approach number 2 is the way to go. (Statics are in general often frowned upon in OOP.)

As I understand it, the method uses this as root, and then traverses the rest of the tree without calling any instance methods? This isn't too bad considering that the other nodes are of the same class, which means that the code is already shared among all objects. (The method can access private members of other instances and so forth.)

That being said, I think getSize, getHeight, getDepth, getPreOrder, getInOrder, getPostOrder and getLevelOrder can all be implemented as proper recursive instance methods. (Correct me if I'm wrong.)

A fourth option which isn't too bad would be to use a visitor pattern and have a NodeVisitor interface.

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • Therefore, in OOP, Is it better to do instance recursive methods than static recursive methods? – RobinHood Jan 28 '15 at 15:06
  • I would argue that that is preferable. Although I think the reasons for that is more on readability and grasping how the code works rather than object orientation principles. I mean traversing the subtree within the method of the root object doesn't violate encapsulation or anything. – aioobe Jan 28 '15 at 17:56
1

Some of those methods definitely should be non-static members since they relate directly to a specific instance.

tree.getSize() or tree.getDepth() is much easier to read and understancd than BinaryTree.getDepth(tree).

However one could argue that the methods getPreOrder(), getInOrder(), getPostOrder() can be static or even in their own class. You can think of that as a StrategyPattern for how to walk the tree.

TraversalStrategy.PREORDER.walk(tree);

might be a good idea instead of adding more methods. That way, if you ever need to add different ways to walk to the tree you don't have to keep adding methods to BinaryTree (Following the Open-Closed Principle)

dkatzel
  • 31,188
  • 3
  • 63
  • 67
  • I think tree.getSize() is the better way to obtain the size of the tree, but the recursive method, which is called by getSize() as getSize(root), could use a node that isn't in the tree like this tree.getSize(nodeOtherTree) and for that I have the question about if these methods may be static or not... – RobinHood Jan 28 '15 at 14:53
  • you can make those static they don't have to be public though – dkatzel Jan 28 '15 at 16:00
0

A class represents a pattern for a set of Objects. A class can have static members and methods, that is, class-level properties and abilities. An instance of a class is an Object, which has its particular, non-static members and methods. In your case, we are talking about a bunch of getters. The key question is:

whose are those methods?

and the answer is: they are methods, that is, abilities of your Tree Object. If you have several Trees, the other Trees have nothing to do with the size and stuff of a given Tree. As a result, all the mentioned methods should be public, instance-level methods unless you want to use them internally, in which case the affected methods should be protected, non-static methods.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
  • 1
    The answer is correct, but these methods use a recursive methods that have a parameter Node which can be Node of the others trees. The question "whose are those methods?" is not as intuitive for this case. – RobinHood Jan 28 '15 at 15:29
  • In fact, it is. You are trying to find a node in the Tree you are processing. It is not relevant that another Tree actually contains the same Node. Your approach should be agnostic, so, if you later try to search a Node which is not present in another Tree, your approach would still be logically viable. Never assume that your current situation will be applicable forever. – Lajos Arpad Jan 28 '15 at 15:34
  • 1
    Yes, it is right, but is not intuitive that you can find a Node of another instace Tree using actual instance Tree e.g. `BTree Tree = new Tree(); BTree AnotherTree = new Tree(); Tree.createTree(Node); AnotherTree.createTree(NodeOfAnotherTree); Tree.getSize(NodeOfAnotherTree);` – RobinHood Jan 28 '15 at 17:00
  • I call this a coincidence. In my view the focus is on the fact that I am searching for the Node inside the current Tree instance. If this does not feel right for you, then you can invent your own strategy, but make sure it is compatible with your teammates, it is effective and easy to use. In my view it is not relevant where the Node comes from, the relevant thing is that we are searching the Node in the tree. – Lajos Arpad Jan 28 '15 at 17:42
  • I think that you consider that Node and NodeOfAnotherTree are the same but it isn't. The recursive method traverse the Tree because the Nodes have an attribute child and for that you could obtain the size of the tree through of this actual Node. The problem is when you do this ` `Tree.getSize(NodeOfAnotherTree)` you obtain the size of AnotherTree not the size of Tree. – RobinHood Jan 29 '15 at 08:53
  • You are searching for similar Node as the parameter in the Tree object. – Lajos Arpad Jan 29 '15 at 10:41