简体   繁体   中英

How to use an interface with methods that has in input or return type the reference of the interface?

I have an interface like that:

public interface IntTree {
    public int getValue();
    public int childrenNumber(); 
    public int nodes (); 
    public int height (); 
    public boolean equals (IntTree t); 
    public void addChild (IntTree child); 
    public IntTree followPath(int[] path);
    public void visit ();
    public void printIntTree ();
}

And I don't know how to implement MyTree because there are a lot of references on the interface: for example:

public void addChild (IntTree child);
public IntTree followPath(int[] path);
public boolean equals (IntTree t);

So I don't understand how to use IntTree reference. I did all my methods with a cast for example:

public class MyTree implements IntTree {
    private int data;
    private LinkedList<MyTree> children; //I have to declare it IntTree or MyTree?

    public MyTree(int data) {
        this.data = data;
        this.children = new LinkedList<>();
    }
    public void addChild(IntTree child){
        this.children.addFirst((MyTree) child);
    }
    public LinkedList<MyTree> getChildren() {
        return this.children;
    }
}

But my teacher said that is wrong to do that, how can I get access for example to my children list etc if I can't cast it to MyTree object? how can I do a method public IntTree followPath(int[] path); if MyTree object = this and it's != from IntTree ? Please explain me, I am getting mad:

And for the other methods that have nothing in input and not return a reference of the Interface I can implement it with the constructor of MyTree ?

If you're allowed to modify the interface declaration then you can change it as following:

public interface IntTree<T extends IntTree<T>> {
    public int getValue();
    public int childrenNumber();
    public int nodes ();
    public int height ();
    public boolean equals (T t);
    public void addChild (T child);
    public T followPath(int[] path);
    public void visit ();
    public void printIntTree ();
}

Then you should declare your class as:

public class MyTree implements IntTree<MyTree>

Now your methods will look like:

public void addChild (MyTree child);
public MyTree followPath(int[] path);
public boolean equals (MyTree t);

So you'll be able to work with them in the way you want.

private LinkedList children; //I have to declare it IntTree or MyTree?

You should use IntTree here as then you'll add elements that implements IntTree interface so it could be a different class object then MyTree . What you're doing is not type safe, take this as example:

public class SomeTree implements IntTree {
    //some code
}

And then lets use SomeTree with our MyTree .

MyTree myTree = new MyTree();
SomeTree child = new SomeTree();

myTree.addChild(child); //Here we get ClassCastException

If you need to implement IntTree interface without changing it then you should leave it as it is without casting. Your code should always be type safe if it is possible.

The equals method is unnecesary, it's already defined in Object. You should override it.

For addChildren, you could store a IntTree list:

public class MyTree implements IntTree {
    private int data;
    private LinkedList<IntTree> children; //I have to declare it IntTree or MyTree?

    public MyTree(int data) {
       this.data = data;
       this.children = new LinkedList<>();
    }

    public void addChild(IntTree child) {
        children.addFirst(child);
    }

    public LinkedList<IntTree> getChildren() {
        return children;
    }

    public IntTree followPath(int[] path) throws NoSuchTreeException {
        for (int i = 0; i < path.length; i++) {
            path[i] = path[i] - 1;
        }

        IntTree oggetto = this;
        for (int i = 0; i < path.length; i++) {
            int index = path[i];
            if (index >= oggetto.getChildren().size() || oggetto.getChildren().isEmpty()) {
                throw new NoSuchTreeException();
            }
            oggetto = oggetto.getChildren().get(i);
        }

        return oggetto;
    }

In "followpath" i changed the type of oggeto asswell.

The key is hold the most general reference while avoiding the casts.

When you define an inteface it means that you are defining all methods that you will use in the class implementation.

In your interface you have the following methods:

public interface IntTree {
    public int getValue();
    public int childrenNumber();
    public int nodes ();
    public int height ();
    public boolean equals (IntTree t);
    public void addChild (IntTree child);
    public IntTree followPath(int[] path) throws NoSuchTreeException;
    public void visit ();
    public void printIntTree ();
}

These methods must be overwritten in MyTree class, for example:

public class MyTree implements IntTree {
    private int data;
    private LinkedList<MyTree> children; //I have to declare it IntTree or MyTree?

    public MyTree(int data) {
        this.data = data;
        this.children = new LinkedList<>();
    }

    public IntTree followPath(int[] path) throws NoSuchTreeException {
        for (int i = 0; i < path.length; i++) {
            path[i] = path[i] - 1;
        }

        MyTree oggetto = this;
        for (int i = 0; i < path.length; i++) {
            int index = path[i];
            if (index >= oggetto.getChildren().size() || oggetto.getChildren().isEmpty()) {
                throw new NoSuchTreeException();
            }
            oggetto = oggetto.getChildren().get(i);
        }

        return oggetto;
    }

    @Override
    public int getValue() {
        return 0; //Implement the logic for this method
    }

    @Override
    public int childrenNumber() {
        return 0; //Implement the logic for this method
    }

    @Override
    public int nodes() {
        return 0; //Implement the logic for this method
    }

    @Override
    public int height() {
        return 0; //Implement the logic for this method
    }

    @Override
    public boolean equals(IntTree t) {
        return false; //Implement the logic for this method
    }

    public void addChild(IntTree child) {
        this.children.addFirst((MyTree) child);
    }

    public LinkedList<MyTree> getChildren() {
        return this.children;
    }

    @Override
    public void visit() {
        //Implement the logic for this method
    }

    @Override
    public void printIntTree() {
        //Implement the logic for this method
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM