0

Sorry, i really dont know how to make a headline for that question; maybe there is a name for what im trying to do that i dont know, but i can explain it with some code:

Guess you have a class that unfortunately neither has a copy-constructor nor a public static copy method.

class A
{
    private int i;  // <- private, cant access
    String x;       // <- even worse: cant access unless in same pkg!
    /* … other stuff, ctor, etc. … */
    public A clone()
    {
        A a = new A();
        a.i = i;
        a.x = x;
        return x;
    }
}

Guess further, there is some function that returns an object of that class:

public static A someFn(x,y,z);

Now the problem: I want to derive from that class to add some functionality. Unfortunately, i neither have a sizeof in java nor a cc or static copy method.

So when i do a

class B extends A
{
    protected w;
    public B clone()
    {
       /* as usual */
    }
}

then i can clone my B and get a new one, but how can i convert the returned A from someFn() into a B. Is there anyway to do the opposite of slicing in java? if i clone it, it's still an A, and i cant copy it field by field. This is all simple in c++, but how to do this in Java?

Bogdan Vasilescu
  • 407
  • 4
  • 22
rhavin
  • 1,512
  • 1
  • 12
  • 33
  • 2
    Your example is a little too abstract. What sort of constructors does A have? How are those private and package-private fields set under normal circumstances? – Michael Myers Mar 23 '11 at 23:03
  • what a messy question... –  Mar 23 '11 at 23:04
  • 1
    If you're talking about cloning in java-sense then when you call `super.clone()` in `B` you'll get `B`. –  Mar 23 '11 at 23:07

4 Answers4

3

Either change the design of A and B to be able to transform an A into a B (if it's even meaningful : how would you transform a dog into a dalmatian?), or use composition instead of inheritance :

public class B {
    private A a;
    private int w;

    public B(A a, int w) {
        this.a = a;
        this.w = w;
    }

    public int foo() {
        return a.foo();
    }

    // ...
}
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Composition would be usefull if java would allow me to overload the cast-operator. I still need the possibility of giving a B for an A. – rhavin Mar 23 '11 at 23:31
  • Then make A and B implement the same interface, and use this interface in the rest of your code rather than A. That's what interfaces are for. – JB Nizet Mar 23 '11 at 23:34
  • to the dalmatian thing: Think you would want to transform a dog into a dog-that-has-an-ID. – rhavin Mar 23 '11 at 23:36
  • I'm not sure I understand. What would all the existing code using A would do with this additional ID it would have as a B instance, since the existing code doesn't know it has an ID property? – JB Nizet Mar 23 '11 at 23:50
  • nothing. but i could use _the same_ object that has additional functionallity. The existing code takes As and provides some overridable fns where they're reappear. I can (and do) stuff Bs (extending A) in and they provide the same functionallity as As plus additional stuff. But then there some existing fns that _create_ As. And i want them to turn to Bs. they dont need to have the same mem location, but i need to copy the A-part into a B. – rhavin Mar 24 '11 at 02:03
1

In java, one does not implement clone() using operator new. I hope you have control over the original Java class - it is not adhering to best practices.

You call super.clone() instead which magically returns an object of the correct type, with the results of the previous clone methods applied to it.

See How to properly override clone method.

Community
  • 1
  • 1
Roman Zenka
  • 3,514
  • 3
  • 31
  • 36
1

First, your clone method is wrong. It sould be something like:

public A clone(){
    A result = (A)super.clone();
    result.i = i;
    result.x = x;
    return result;
}

While the clone for B:

public B clone(){
    B result = (B)super.clone():
    result.w = w;
    return result;
}

You could have a constructor in B which takes an instance of A, pulls out the data it requires from that instance of A, and creates the B object with it.

Then, you could call someFn(x,y,z) like:

B b = new B(someFn(x, y, z))

Also if someFn wouldn't have been static, you could have written a subclass for the class that defines it, and override someFn changing it's return type like (this feature is called covariant return type):

B someFn(x, y, z){
   ...
}
Ioan Alexandru Cucu
  • 11,981
  • 6
  • 37
  • 39
0

Unfortunately, the only way left was a complete wrapper mimicing the functionality i needed, buyed with some overhead in performance.

Its completly stupid that there is no way to provide a class for clone to clone into…

rhavin
  • 1,512
  • 1
  • 12
  • 33