Java Inheritance Maximize reuse - java

In following example, TreeNode is the superclass and BinaryNode is subclass.
public class TreeNode {
private int data;
private TreeNode parent;
private List<TreeNode> children;
TreeNode() {
this.data = 0;
this.parent = null;
this.children = new ArrayList<TreeNode>();
}
}
In subclass, every node has only two children.
I write as following.
How should I write the member fields and constructor to best use the superclass, yet keep the structure right?
public class BinaryNode extends TreeNode {
// int data;
// BinaryNode parent;
List<BinaryNode> children;
BinaryNode() {
super();
children = new ArrayList<BinaryNode>(2);
}
}
in constructor BinaryNode(), super() is called, what's the impact on children?
What's more, if the subclass has specific rules on some fields, like only two children in this sample, how to write the constructors in superclass and subclass to maximize reuse?
if I have the following method isLeaf() in superclass and don't write it in subclass.
When I try to use it with a subclass instance, would it function correctly?
public boolean isLeaf() {
if(this.children == null)
return true;
else
return false;
}

You mark the attributes protected in the superclass and the subclass should have access to them:
public class TreeNode {
protected int data;
protected TreeNode parent;
protected List<TreeNode> children;
...
public boolean isLeaf() {
if(this.children == null)
return true;
else
return false;
}
}

Related

Build Logic Tree like the where clause in sql

I want to build a Logic Tree in Java which contains the conditions that could be used
for database insertions.
for example:
Node tree = input0.eq(3).and(input1.eq(1).or(input2.greaterThan(5)));
could be converted to:
WHERE input0=3 AND (input1 = 1 OR input2 > 5)
Since a Node could be a logical expression like and,or etc. as well as a Leaf with data, I thought a parent Node class and two child classes, would be ideal. But I have no idea how to handle nested expressions. I already read a few similiar questions here, but they weren't really specific enough.
public class Node {
public Long id;
public Node parent;
public List<Node> children;
}
public class LogicalNode extends Node {
LogicType logicType;
public LogicalNode () {
super();
}
getter and setter...
}
public class LeafNode extends Node {
Object input;
public LeafNode () {
super();
}
getter and setter...
}
public enum LogicType
{
AND("and"),
OR("or"),
NOT("not"),
EQ("="),
GREATER_THAN(">"),
LESSER_THAN("<");
private String name;
LogicType (String name) {
this.name= name;
}
public String getName() {
return name;
}
}
To get you started, try something similar to this:
public abstract class Node {
abstract void toSql();
Node eq(Node other) {
return new LogicalNode(LogicalType.EQ, this, other);
}
...
}
public class LeafNode extends Node {
LeafNode(int value) {
this.value = value;
}
String toSql() {
return this.value.toString();
}
}
public class LogicalNode extends Node {
LogicalNode(LogicalType type, Node left, Node right) {
this.logicalType = type;
this.left = left;
this.right = right;
}
String toSql() {
return String.format(
"(%s) %s (%s)",
this.left.toSql(),
this.logicalType.getName(),
this.right.toSql()
);
}
}
The key here is that the LogicalNode is constructed using two other Nodes, but it doesn't concern itself with whether or not they are LeafNodes or LogicalNodes. All LogicalNode knows is that it has two things that can be converted to a string using toSql.

setParent(this) with Java generics

I have a generic Element class which contains elements of the same class. Based on that I would then create concrete classes like
Boxes extends Element<Boxes>
The point I don't get is the
setParent(this);
Why do I need to cast it
setParent((C) this);
(and suppress type casting warnings)? Obviously I am missing something...
How would you change the class to have no casting and no warnings?
I would argue that "this" is a Element object (at minimum) and C as well.
public class Element<C extends Element<C>> {
List<C> children;
C parent = null;
public Element() {
}
void setChildren(List<C> children) {
this.children = children;
for (C c : children) {
c.setParent((C) this); // warning, without the cast: error
}
}
void setParent(C parent) {
this.parent = parent;
}
You get this error because this is of type Element<C> and not of type C.
The following would work:
public class Element<C extends Element<C>> {
List<C> children;
Element<C> parent = null;
public Element() {
}
void setChildren(List<C> children) {
this.children = children;
for (C c : children) {
c.setParent(this);
}
}
void setParent(Element<C> parent) {
this.parent = parent;
}
}
Btw, IDEs are pretty good explaining why you get such errors.
Because nothing guarantees that this is of type C.
For example, you could create an object this way:
Element<Boxes> e = new Element<>();
or this way:
class Container extends Element<Boxes> {}
...
Container c = new Container();
You can add protected abstract C self() method to Element<C> class and use it instead of (C) this:
public abstract class Element<C extends Element<C>> {
List<C> children;
C parent = null;
protected abstract C self();
void setChildren(List<C> children) {
this.children = children;
for (C c : children) {
c.setParent(self());
}
}
void setParent(C parent) {
this.parent = parent;
}
}
Now when you extend Element<C> you can implement self() just by returning this:
public class Boxes extends Element<Boxes> {
#Override
protected Boxes self() {
return this;
}
}
This is a pretty popular design. You can see it, for example, if you delombok builders which are generated with Lombok #SuperBuilder annotation:
public class Example {
private final int someField;
protected Example(ExampleBuilder<?, ?> b) {
this.someField = b.someField;
}
public static ExampleBuilder<?, ?> builder() {
return new ExampleBuilderImpl();
}
public static abstract class ExampleBuilder<C extends Example, B extends ExampleBuilder<C, B>> {
private int someField;
public B someField(int someField) {
this.someField = someField;
return self();
}
protected abstract B self();
public abstract C build();
public String toString() {
return "Example.ExampleBuilder(someField=" + this.someField + ")";
}
}
private static final class ExampleBuilderImpl extends ExampleBuilder<Example, ExampleBuilderImpl> {
protected Example.ExampleBuilderImpl self() {
return this;
}
public Example build() {
return new Example(this);
}
}
}

Extending vs. implementing Comparable in java [duplicate]

This question already has answers here:
What is PECS (Producer Extends Consumer Super)?
(16 answers)
Closed 4 years ago.
I'm trying to implement binary search tree in java. It can take any object as the data of a node in the tree, as long as that object implements the Comparable interface. This is needed because while putting a new node in the tree, we need to decide, whether the new node is of lesser or greater value compared to its parent. My Node class looks something like the following.
package com.java.ds.bst;
public class Node<T extends Comparable<T>> implements Comparable<T> {
private T data;
private Node<T> left = null;
private Node<T> right = null;
public Node() {
this.data = null;
}
public Node(T data) {
this.data = data;
}
public T getValue() {
return this.data;
}
public Node<T> getLeft() {
return this.left;
}
public Node<T> getRight() {
return this.right;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public void setRight(Node<T> right) {
this.right = right;
}
#Override
public int compareTo(T other) {
return this.data.compareTo(other);
}
}
What I don't understand is, in the class name declaration, why do I need T extends Comparable<T> instead of T implements Comparable<T>?
It is the syntax for generics, T extends Comparable<T> means it will accept anything that is Comparable<T>.
You are correct to use implements Comparable<T> when implementing the interface.

Java how to return a generic type that extends an interface

I have an interface named IDedObject and I am making a linkedlist class that uses generics that extend the IDedObject interface. In the linkedList class, I have a function that tries to find a given item based on it's data, and then returns that item. I am getting an error that says
Incompatible types. Required: AnyType. Found: IDedObject
This is what my code looks like:
Interface:
public interface IDedObject {
public int getID();
public void printID();
}
LinkedList:
public class singlyLinkedList<AnyType extends IDedObject> {
public Node<AnyType> endMarker;
public Node<AnyType> beginMarker;
AnyType findID(int ID){
Node curNode = beginMarker;
while(curNode.getNext() != endMarker){
if (curNode.getData().getID() == ID){
return curNode.getData();
}
}
return null;
}
}
class Node<AnyType extends IDedObject>{
public Node(AnyType d, Node<AnyType> n){
data = d;
next = n;
}
public Node getNext(){
return next;
}
public AnyType getData() {
return data;
}
public AnyType data;
private Node<AnyType> next;
private int theSize;
}
I appreciate any help with this. It's for a homework assignment, so i'm required to use a generic the extends IDedObject.
Thanks.
I fixed the problem by changing
Node curNode = beginMarker;
to
Node<AnyType> curNode = beginMarker;
in the findID function in the LinkedList class. Not sure how I missed that.

compareTo is asking me to cast, and I do not know why

Can someone explain why I am getting this error: The method compareTo(AVLNode) is undefined for the type AVLNode
Here is a shortened version of my Tree class:
public class AVLTree< E extends Comparable<E> >
{
private AVLNode<E> root ;
public AVLTree()
{
this.root = null;
}
public void insert ( AVLNode<E> item )
{
if( item.getLeft().compareTo(item.getItem() ) < 0) //ERROR IS HERE
{
}
}
}
Below is my a short version of my Node class
class AVLNode <E extends Comparable<E> >
{
private AVLNode<E> item;
private AVLNode<E> left;
public AVLNode ( AVLNode<E> item)
{
this.item = item;
this.left = null;
}
public AVLNode( AVLNode<E> item, AVLNode<E> lft )
{
this.item = item;
this.left = lft;
}
public AVLNode<E> getItem()
{
return this.item;
}
public AVLNode<E> getLeft()
{
return this.left;
}
}
Your Comparable base class assumes you're comparing to Es when you want to compare to AVLNode<E>s
So change it to inherit Comparable<AVLNode<E>> and see what happens.
Your AVLNode class should obviously look like this:
public class AVLNode<E extends Comparable<E>> {
private E item;
//...
public int compareTo(final E obj) {
return this.item.compareTo(obj);
}
Difference:
item should be of type E not AVLNode<E> because you want to store an E and not a AVLNode.
To state, that your AVLNodes are comparable, they could implement Comparable<T> themself by just delegating to E#compareTo() method:
public class AVLNode<E extends Comparable<E>> implements Comparable<AVLNode<E>> {
private E item;
//...
#Override
public int compareTo(final AVLNode<E> other) {
return this.item.compareTo(other.item);
}
}
getLeft() returns an AVLNode. You try and call getLeft().compareTo(...). This requires that AVLNode provides a matching method.
From this:
class AVLNode <E extends Comparable<E> >
{
private AVLNode<E> item;
...
It looks like your nodes can only hold other nodes. Presumably your items should actually be of the comparable type E. Then you can retrieve the item and call compareTo() on that.
That's because AVLNode doesn't have a method called compareTo() if you implement one then the issue should be solved.
You should also decide whether your want to compare E vs E or AVLNode vs AVLNode

Categories