views:

298

answers:

5

Can you take a subclass object and somehow convert it to an object of the same type as the parent class and at the same time slicing all the fields that are not part of the parent class?

I know you can do this in C++, but I have no idea how to do it in Java.

+5  A: 

You cannot change the runtime type of an object in Java (though you can assign a reference to and object to a supertype, and cast back to a subtype). You would need to construct a new object of the superclass runtime type.

I would generally recommend that all classes should be abstract or leaf (conceptually final, if not actually marked as such for pragmatic reasons).

Tom Hawtin - tackline
Everything abstract or final? That sounds a bit extreme.
miorel
Why would you have all your classes be abstract or leaf?
Joel
I don't abide by that particular mantra, but in practice I find that seems to be the case anyway. As Joshua Bloch says (to paraphrase), "Either plan for extension or forbid it". All abstract or final classes is the logical extreme of that philosophy.
Jason Nichols
`abstract^final` is not supposed to be popular. It's supposed to be good for your code.
Tom Hawtin - tackline
@Tom: Also Scott Meyers gives the advice: 'Make non-leaf classes abstract.' in *More Effective C++*.
quamrana
@miorel: btw, Joshua Bloch said *"final is the new private"* and strongly recommends making *everything* final. The technique suggested by Tom Hawtin is a good start. I go even further: 200KLOC here and there isn't a single class that is not final. Better, there isn't a single abstract class. Because I don't believe in "code reuse" (I much prefer delegation and multiple inheritance) and because I think that it's even better for the code when you're not relying on implementation details...
Webinator
@Jason Nichols: preventing extension of concrete implementations, sure. But that doesn't prevent you from having a nice adaptable design where you model *everything* using Java interfaces (aka C++ pure abstract classes) even though all of your classes are final.
Webinator
@WizardOfOdds IIRC, "final is the new private" refers to fields (which always were `final` where appropriate to me anyway). Non-final fields annoy the hell out of me when I'm auditing mountains of code.
Tom Hawtin - tackline
A: 

There is no direct analog of slicing in Java, but I'm sure you can simulate this by adding a member function to either the parent or child that will create a new parent instance for you.

quamrana
+3  A: 

Try this:

class Parent {
    private int fieldA;

    Parent(int fieldA) {
        this.fieldA = fieldA;
    }

    Parent(Parent object) {
        this.fieldA = object.fieldA;
    }
}

class Child extends Parent {
    private int fieldB;

    Child(int fieldA, int fieldB) {
        super(fieldA);
        this.fieldB = fieldB;
    }
}

Then you can do something like Parent parent = new Parent(child); and you will achieve the desired result, but as others commented this won't be a conversion but rather construct an entirely new object.

miorel
Just to take it a step further class myParent<T extends myParent>{ // myParent fields here myParent( T someDescendant ){ // copy only the fields visible to myParent here } }
Everyone
I'm not sure why you're adding generics in there...
miorel
A: 

I haven't seen type-slicing in Java. And i don't think there's much need of it...

You can anytime do this in Java

Object x = new String("hello");

Here you will not have all the functions that String class provides

Webbisshh
True, but you will still get the String version of any Object methods which are overridden.
miorel
“Java” is not, and has never been, an acronym.
Konrad Rudolph
Thanks for reminding :) ... that was a bad habit i got!
Webbisshh
A: 

Im not sure why you want to do this, but you could have two classes implement the same interface, then reference the objects by the interface. For example:

class A implements something...
class B implements something...

something = new A();    
something = new B();
John
Why the downvote, this would effectively do what the person was asking. Have class B extend A.
John
Then you could have: A a=new A();B b=new B();Then you could do something like: something s1=a;something s2=b;
John
You could also just do (if B extends A): A tmp=b;
John