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.
because if B extends C, it means B is a C and not C is a B.
rethink what you are trying to do.
The existing answers are fine in terms of an abstract argument, but I'd like to make a more concrete one. Suppose you could do that. Then this code would have to compile and run:
// Hypothetical code
Object object = new Object();
InputStream stream = (InputStream) object; // No exception allowed?
int firstByte = stream.read();
Where exactly would the implementation of the read method come from? It's abstract in InputStream. Where would it get the data from? It simply isn't appropriate to treat a bare java.lang.Object as an InputStream. It's much better for the cast to throw an exception.
In my experience it's tricky to get "parallel class hierarchies" like the one you're describing to work. You may find that generics help, but it can get hairy very quickly.
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" );
}
}
You can create a constructor for B that takes C as a parameter.
See this post for ideas to do what you're trying to do.
Base classes shouldn't know anything about classes derived from them, otherwise the problems highlighted above will arise. Downcasting is a 'code smell', and downcasting in the base class to a derived class is particularly 'smelly'. Such designs can lead to difficult to resolve circular dependencies too.
If you want a base class to make use of derived class implementations use the Template method pattern i.e add a virtual or abstract method in your base class and override and implement it in the derived class. You can then safely call this from the base class.
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.
In your exemple, you can cast n into a DerivedNode if you are certain that n is an instance of DerivedNode, or you can use generics:
public class Base<N extends BaseNode> {
protected N n;
public void foo(BaseNode x){
n.foo(x);
}
}
public class BaseNode {
public void foo(BaseNode x){...}
}
public class Derived extends Base<DerivedNode> {
public void bar(DerivedNode x){
n.bar(x); // no problem here - n DOES have bar
}
}
public class DerivedNode extends BaseNode {
public void bar(BaseNode){
...
}
}
Because if B extends C, then B might have stuff that isn't in C (like instance variables you initialize in the constructor that are not in new C())
Related
I know that you can use super.super.methodName() to invoke the grandparent's version of a method, but is there any way to directly invoke the grandparent class's constructor in a chained constructor call?
(Simplified) Example:
class A {
public A(){}
public A(int i, boolean b) {
/*...*/
}
}
class B extends A {
public B(){}
public B(int i) {
super(i, true);
}
}
class C extends B {
public C(int i)
{
super.super(i,false); //This is not allowed, but you
//can see what I'm trying to do (call A(i,false).)
//this=new A(i,false); also doesn't work b/c this can't be LHS
//of assignment
}
}
..or is this disallowed, and did I just demonstrate the reasoning for doing so in attempting to make a super.superclass(grandparent) constructor call not possible in the (parent)superclass?
No, and this is by design. The intermediate class intentionally hides some of the functionality of its superclass, and the constructor is one area where it does so.
Think about it like this. Suppose you have three classes: Animal, Dog, Terrier.
Dog extends Animal
Terrier extends Dog
In your Terrier constructor, it's quite appropriate for it to call the Dog constructor. What you're doing is to say that when a Terrier is created it should do its doggy-related thing, and then afterwards do anything terrier-specific.
But what you're wanting to do is to get the Terrier constructor to invoke the Animal constructor. This is essentially to say that the Terrier should set itself up without regard for the fact that it's a dog. Anything might now happen: the code to initialize the fields needed for the .woof() method won't get dealt with, for instance. Now your Terrier is in a terrible mess when it tries to woof later.
If you're wanting your Terrier to do some Animal setup but avoid the Dog setup, that suggests that your class hierarchy is all wrong: your Terrier probably isn't a Dog at all.
No. But you can get around it.
You can call super.foo(), then in your parent foo method, you call super.foo()
For instance
class A {
public void foo() {
System.out.println("I want this");
}
}
class B extends A {
public void foo() {
super.foo();
}
}
class C extends B {
#Test
public void callFooTest() {
C c = new C();
c.foo();
//call foo() and you will get the one from Class A
}
}
The same works for constructors
I came across the following Java code that uses generics and inheritance. I truly do not understand what the following snippet does:
class A<B extends A<B>> {
...
}
What does this code do?
(I got this from DBMaker in MapDB)
It is almost clear and the question actually conists in two parts:
1) why B extends A?
2) why A inside B extends A<B> has generic type B?
Answers for these parts will be:
1) In particular example this class (A) is builder class (called DBMaker), so most of its methods return some type, which extends this builder's class type. This explains, why B should extend A class.
2) But, actualy, if we will hide for the second part ...extends A<B>, we will receive just class A<B>. So A has type variable of type B. That is why in ...extends A<B> A is marked as type A having type variable B.
This tells that A needs derived definitions to be able to do some work:
public abstract class A<T extends A<T>> {
protected T instance;
T getOne() {
return instance;
}
}
public class B extends A<B> {
public B() {
instance = this;
}
}
public static void test() {
B b = new B();
b.getOne();
}
This is most commonly used in interface definitions, where one wants to explicitly use instances of classes implementing an interface in return types or in arguments and not the interface itself:
public interface TimeSeries<T extends TimeSeries<T>> {
T join(T ts);
}
public class DoubleTimeSeries implements TimeSeries<DoubleTimeSeries> {
#Override
public DoubleTimeSeries join(DoubleTimeSeries ts) {
return null;
}
}
So I did some tests to figure this one out, and here is my test cases to see how one could use such a generic case:
public class A<B extends A<B>> {
int x = 10;
B test;
void printX() {
System.out.println(x);
}
void setB(B b) {
test = b;
}
void printB() {
System.out.println(test);
}
}
public class B extends A<B> {
}
public class Run {
public static void main(String[] args) {
A<B> test = new A<B>();
B myB = new B();
test.printX();
test.setB(myB);
test.printB();
myB.printB();
}
}
I hope the code might be self explanatory. If not leave a comment and I will try and explain what is going on. Look at the last line, myB.printB(), here we will get a null, because B has not yet been set for myB, but only for test. This demonstrates that we can have an infinite recursion into classes of B inside A (and inside B for that matter).
we can say:
myB.test.printB();
This will get an error (null pointer), but shows that we now have access to test in the A class from B, and we can go as deep as we want recursively with as many cases as we like. So the A class kind of functions as a wrapper of infinitely many B classes. Does this make sense?
This makes it easier when defining method return types such as this:
class A<B extends A<B>> {
public B getMe(){
return (B) this;
}
}
This tells Java compiler that you are in getMe() method returning a subclass of class A.
class C extends A<C> {
}
C c = new C();
c.getMe(); //returns C
I have the following classes:
public abstract class A implements C {
...
}
public abstract class B extends A {
method();
}
But when I try to do the following
A a = null;
A a = new A();
((B) a).method();
I receive a ClassCastException, does anyone have a solution?
B extends A, but A doesnt extend B.
everything A has B has, but A cant do the stuff declared in B
An instance of B is an instance of A, but an instance of A is not necessarily a B. Similar to saying "all circles are shapes, but not all shapes are circles".
You can't do what you are trying to do. That's why you get the exception.
I think what you want here is a constructor to take and A object and make a larger B object out of it which has the included method (which A does not have). But that doesn't make a whole lot of sense. Cant think for the life of me why you would want to do this in practice, and wouldn't just build the B object to start with.
public abstract class A implements C {
...
}
public abstract class B extends A {
public B(A child){
//Construct a B out of A here
}
public void method();
}
Then
A a = null;
A a = new A();
new B(a).method();
Example : How would I make furtherSpecificProcessing method a private method?
Reason: I would like to be able to new an object of type B or C and only have doStuff() visible to programmer. while at the same time class B and C supply the additional functionality
abstract class A
{
protected abstract void furtherSpecificProcessing();
//concrete method utilizing abstract method
public void doStuff()
{
//busy code
furtherSpecificProcessing();
//more busy code
}
public class B extends A
{
public void furtherSpecificProcessing
{
//Class B specific processing
}
}
public class C extends A
{
public void furtherSpecificProcessing
{
//Class C specific processing
}
}
I don't think you can force return type to be private for overriding method.
Access Must not be more restrictive. Can be less restrictive.
I would suggest reading method overriding rules.
Override furtherSpecificProcessing() as protected, not as public in extending classes.
Declare the method as protected instead of public in both classes B and C.
Than what you need will work :
B b = new B();
b.doStuff(); // Will do stuff
b.furtherSpecificProcessing(); // Will not compile
and the same goes for instances of class C
I have a number of classes, please allow me to introduce them and then ask my question at the end:
I have a container class which contains two objects in a composite relationship:
public class Container{
A a;
B b;
public someMethod(){
a.getC().myMethod(b);
}
}
A and B are superclasses (or Interfaces), with subtypes that can also be the type held in the composite relationship.
A contains a member of (interface) type C:
public class A{
C c;
}
public interface C{
public void myMethod(B b);
}
public class D implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
public class E implements C{
public void myMethod(B b){
//This code will modify the state of object b, in class Container.
b.changeState();
}
}
My problem is that I wish to modify the state of object b from a method starting in the container class, which eventually calls code down the hierarchy, to classes D and E- calling myMethod() via dynamic binding. I want to do this because I am going to use polymorphism to run the correct myMethod() (depending on whether the type of object is D or E) and I wish to do this, rather than write IF statements.
So my problem is that it seems very bad continually passing the instance of object b down the class hierarchy to myMethod, so that I can run b-specific code to modify the state of b. Is there anything else I can do to modify b from d and e (collectively known as c)?
I can get this to work using just interfaces but without using generics- but when I added generics i had problems with types and that made me start to think if my whole design was flawed?
EDIT: I could probably do this easily just by using IF statements- but I wanted an elegant solution using polymorphism of classes D and E.
First of all, if I understood your question correctly, no instance of B is being "passed down" in your code. Dynamic dispatch will simply cause the myMethod() implementation in the actual type of a to be called with an instance of B as argument.
While it may be tedious to have to write the argument explicitly every time you implement myMethod(), there's nothing wrong with it.
The alternative is to give each subclass/implementation of A an attribute of type B. In this case, however, you would have to pass your B instance down the chain of constructors to the class that actually has your B attribute.
Your code would become:
public class A{
C c;
public A(C c) {
this.c = c;
}
public interface C{
public void myMethod(B b);
}
public abstract class CC {
protected B b;
public CC(B b) {
this.b = b;
public class D extends CC implements C {
public D(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
public class E extends CC implements C {
public E(B b) {
super(b);
}
public void myMethod(){
b.changeState();
}
}
And then somewhere, e.g. in Container's constructor:
b = new B();
a = new A(new E(b));
You could pass the instance of B to the constructor of E. (or use a setter). That poses issues in itself, but at least it avoids having to pass B down every time you call myMethod(), which now needs no arguments.
e.g.
somewhere inside B
E myE = new E(this);
and, inside E
final B myB;
public E(B myHigherLevelThing) {
this.myB = myHigherLevelThing;
}
public void myMethod() {
myB.changeState();
}
Use the most general interface for the declarations, I'm a little confused about your full hierarchy so there may be room for improvement there...