-1

I've got an external class I cannot modify and I want to add customized functionality to that class related to my project, so I created a class which extends it in order to add the extra methods I need.

The problem is that Car class doesn't have a constructor, so I can't use super, the only way to create a Car object is through a native method that returns a fully filled Car object.

public class Car {
    //The only way to create a car  
    public native Car readFromFile (String file);

    //Many other variables and methods

}

And my custom class:

import com.example.Car;

public class CustomCar extends Car {
    public void extraMethod1(){
        //do something using Car variables
    }
}

Obviously I cannot cast to (CustomCar) as I have ClassCastException, so how can I get a Car from that native method and use on that object the methods from CustomCar?

Should I just have a variable Car in CustomCar and use it in CustomCar methods?

import com.example.Car;

public class CustomCar {
    Car car;
    public void extraMethod1(){
        car.doSomething(); //do something using Car variables

    }
}

Or should I just create a new constructor copying all the parents variables?

Many thanks for your help!

jordileft
  • 39
  • 6

1 Answers1

1

I suspect that your question may be based on a misconception. Your example class Car has a default constructor that is equivalent to writing this:

    public Car() { }

The default constructor is added if and only if a class doesn't declare any explicit constructors.

If you declare CustomCar as a subclass of Car it can use the default Car constructor.


A second issue is that you have declared readFromFile as

    public native Car readFromFile (String file);

it has to be

    public static native Car readFromFile (String file);

to be usable. (If readFromFile is genuinely an instance method, and genuinely the only way that Car instances get created, then you have a bootstrapping problem. How do you create the first Car?)


Having said that, if the default constructor for your Car class doesn't work (i.e. it doesn't initialize the state of a Car correctly) then you have a problem:

  • If CustomCar(...) simply uses Car(), the superclass will not be properly initialize.

  • If it class Car.readFromFile() the result will be a new object that is a Car, not a CustomCar.

There are possibly some ways to work around this. For example:

  • You could add an explicit constructor to Car that does the necessary initialization.

  • You could implement CustomCar as a wrapper for a real Car instance that CustomCar instantiates using the native Car method. Then have the CustomCar implementation delegate to the wrapped instance. If there are no other problems, you should be able to make CustomCar a subtype of Car.

Which approach is better? It is hard to say. It depends on details of your real use-case; e.g. does the object created by the native method have hidden state, or special "identity related" properties? (Why are you creating it using native code?)


If there reasons that these workarounds won't work, then you have a problem. There is no way that Car::readFromFile can be the constructor that any Car subclass requires.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • You are right @StephenC , I forgot the static on the native method... The Car class is from an external library, so it was not my choice to use a native method, I guess they did that in order to protect intellectual property. Default constructor doesn't work for me, so probably the wrapper solution will be the best in this case, 'cause that external library might be externally updated from time to time, so an explicit constructor could get outdated or demand to be updated regularly. As I'm not an expert on programming I thought maybe I was missing something else. Thanks for your help! – jordileft Mar 14 '19 at 14:07