Java; casting base class to derived class

2019-04-18 22:16发布

Why can't I cast a base class instance to a derived class?

For example, if I have a class B which extends a class C, why can't I do this?

B b=(B)(new C());

or this?

C c=new C();
B b=(B)c;

Alright let me be more specific as to what I'm trying to do. Here's what I have:

public class Base(){
    protected BaseNode n;
    public void foo(BaseNode x){
        n.foo(x);
    }
}


public class BaseNode(){
    public void foo(BaseNode x){...}
}

Now I want to create a new set of classes which extend Base and Basenode, like this:

public class Derived extends Base(){
    public void bar(DerivedNode x){
        n.bar(x);//problem is here - n doesn't have bar
    }
}

public class DerivedNode extends BaseNode(){
    public void bar(BaseNode){
        ...
    }
}

So essentially I want to add new functionality to Base and BaseNode by extending them both, and adding a function to both of them. Furthermore, Base and BaseNode should be able to be used on their own.

I'd really like to do this without generics if possible.


Alright so I ended up figuring it out, partly thanks to Maruice Perry's answer.

In my constructor for Base, n is instantiated as a BaseNode. All I had to do was re-instantiate n as a DerivedNode in my derived class in the constructor, and it works perfectly.

8条回答
小情绪 Triste *
2楼-- · 2019-04-18 23:07

You need to use the instanceof keyword to check the type of object referenced by n and typecast the object and call the bar() method. Checkout Derived.bar() method bellow

public class Test{
    public static void main(String[] args){
        DerivedNode dn = new DerivedNode();
        Derived d = new Derived(dn);
        d.bar( dn );
    }
}

class Base{
    protected BaseNode n;
    public Base(BaseNode _n){
        this.n = _n;
    }

    public void foo(BaseNode x){
        n.foo(x);
    }
}


class BaseNode{
    public void foo(BaseNode x){
        System.out.println( "BaseNode foo" );
    }
}

class Derived extends Base{
    public Derived(BaseNode n){
        super(n);
    }

    public void bar(DerivedNode x){
        if( n instanceof DerivedNode ){
            // Type cast to DerivedNode to access bar
            ((DerivedNode)n).bar(x);
        }
        else {
            // Throw exception or what ever
            throw new RuntimeException("Invalid Object Type");
        }
    }
}

class DerivedNode extends BaseNode{
    public void bar(BaseNode b){
        System.out.println( "DerivedNode bar" );
    }
}
查看更多
冷血范
3楼-- · 2019-04-18 23:07

You can't do that because C does not necessarily implement the behaviours you created when you extended it in B.

So, say C has a method foo(). Then you know that you can call foo() on a B, as B extends C, so you can cast accordingly a treat a B as if it was a C with (C)(new B()).

However - if B has a method bar(), nothing in the subclass relationship says that you can call bar() on C too. Thus you cannot treat a C as if it were a B, and so you cannot cast.

查看更多
登录 后发表回答