I'm having a bunch of classes that I can not change; all these classes have a common ancestor (other than Object) that declares and implements the majority of their properties and methods.
Let's say, we have an inheritance tree like this (for illustration only):
class Vehicle
class Bicycle extends Vehicle
class Skateboard extends Vehicle
class Boat extends Vehicle
class Car extends Vehicle
class Aircraft extends Vehicle
class Jetplane extends Aircraft
class Helicopter extends Aircraft
...
class Truck extends Vehicle
...
While class Vehicle is actually more like an abstract class (it is not really, but it is never instantiated on its own behalf), objects of class Aircraft are created occasionally.
Now the point: the objects can have interrelationships that are not reflected by the classes. Since it is quite a bouquet of classes and the collection is subject to change every once in a while, it is not practical to maintain a subclass for each of the classes that implement the missing behavior.
My approach is therefore to have one class that serves as a wrapper for the above classes.
The constructor takes as a parameter the class of the respective object, which is then instantiated using reflection.
class VehicleW
{
// fields
public boolean isInitialized=false;
private Vehicle fVehicle;
...
// constructors
public VehicleW(Class aClass, ...)
{
Class VehicleClass = Vehicle.class;
if (!VehicleClass.isAssignableFrom(aClass))
return;
// <the reflection magic here>
...
// and on success mark this object as usable
isInitialized=true;
}
}
A constructor without arguments doesn't really make sense here. But now class Aircraft and its subclasses want some extra properties, so I thought I could establish a class AircraftW extends VehicleW that takes care of them.
The modification then looks like this:
// fields
private Aircraft fAircraft;
// constructors
public AircraftW(Class aClass, ...)
{
Class AircraftClass = AirCraft.class;
if (!AircraftClass.isAssignableFrom(aClass))
return;
// <the reflection magic here>
...
// and on success mark this object as usable
isInitialized=true;
}
But this fails, because Java intelligently inserts a call to the parameterless constructor of the ancestor, which is not present (and doesn't make sense, as already said).
It also doesn't make sense to call the parameterized super(), because I initialize a field of class Vehicle then. Okay, I can later in my AircraftW() just set that field to null, but that doesn't seem right.
Is there a way around this? Or am I taking an absolutely wrong approach? I thought about generics, but I can't seem to find a point using it. Interfaces? I'm not that much of a Java expert, so any recommendations are welcome.
Edit (not unsolved (to avoid the term solved)) Well, below you find a working program. I can't put it down as an answer, because Thomas led me to this code... with his answer... which I accepted as the solution... I can't see what's wrong with that.
Thanks, Thomas, for pointing me in the right direction.
For the sceptical, here the complete source code of a test program:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Vehicle { public Vehicle(){} }
class Bicycle extends Vehicle { public Bicycle(){} }
class Skateboard extends Vehicle { public Skateboard(){} }
class Boat extends Vehicle { public Boat(){} }
class Car extends Vehicle { public Car(){} }
class Aircraft extends Vehicle { public Aircraft(){} }
class Jetplane extends Aircraft { public Jetplane(){} }
class Helicopter extends Aircraft { public Helicopter(){} }
class Truck extends Vehicle { public Truck(){} }
class VehicleW
{
protected Vehicle fVehicle=null;
public boolean isInitialized=false;
public VehicleW(Class aClass)
{
if (checkVehicle(aClass))
if ((fVehicle=makeVehicle(aClass))!=null)
isInitialized=true;
}
protected boolean checkVehicle(Class aClass)
{
Class tClass = Vehicle.class;
return (tClass.isAssignableFrom(aClass));
}
protected Vehicle makeVehicle(Class aClass)
{
Vehicle tVehicle = null;
System.out.format("trying to create %s\n",aClass.toString());
Constructor c;
try
{
c=aClass.getConstructor();
}
catch(NoSuchMethodException e)
{
System.out.format(" no constructor found\n");
return null;
}
try
{
tVehicle=(Vehicle)c.newInstance();
}
catch(InvocationTargetException e)
{
System.out.println(e.toString());
}
catch(InstantiationException e)
{
System.out.println(e.toString());
}
catch(IllegalAccessException e)
{
System.out.println(e.toString());
}
return tVehicle;
}
public Vehicle getVehicle()
{
if (!isInitialized)
return null;
return fVehicle;
}
public Class getWClass()
{
if (!isInitialized)
return null;
return fVehicle.getClass();
}
}
class AircraftW extends VehicleW
{
public AircraftW(Class aClass)
{
super(aClass);
/*
Class tClass=Aircraft.class;
if (!tClass.isAssignableFrom(aClass))
return;
isInitialized=true;
*/
}
#Override
protected boolean checkVehicle(Class aClass)
{
Class tClass = Aircraft.class;
return (tClass.isAssignableFrom(aClass));
}
}
class program
{
public static void tellme(VehicleW vx)
{
String s = "failed";
if (vx.getVehicle()!=null)
s="succeeded";
System.out.format(" making %s for %s %s\n",
vx.getWClass(),vx.getClass(),s);
}
public static void main(String[] args)
{
VehicleW v1, v2, v3;
AircraftW a1, a2, a3;
v1=new VehicleW(Bicycle.class);
tellme(v1);
v2=new VehicleW(Boat.class);
tellme(v2);
v3=new VehicleW(Helicopter.class);
tellme(v3);
a1=new AircraftW(Helicopter.class);
tellme(a1);
a2=new AircraftW(Aircraft.class);
tellme(a2);
a3=new AircraftW(Truck.class);
tellme(a3);
return;
}
}
and the output:
trying to create class Bicycle
making class Bicycle for class VehicleW succeeded
trying to create class Boat
making class Boat for class VehicleW succeeded
trying to create class Helicopter
making class Helicopter for class VehicleW succeeded
trying to create class Helicopter
making class Helicopter for class AircraftW succeeded
trying to create class Aircraft
making class Aircraft for class AircraftW succeeded
making null for class AircraftW failed
This sounds a lot like the factory pattern so you might want to look into that.
What you basically would do is something like this:
class VehicleFactory {
public static Vehicle createAircraft( /*Aircraft specific parameters*/) {
//build and return Aircraft, you can call your reflection magic here
}
public static Vehicle createBoat( /*Boatspecific parameters*/) {
//build and return Boat, you can call your reflection magic here
}
}
Additionally, you might want to look into the builder pattern.
In your approach there are several issues:
Prematurely returning from a constructor would still kept the created object, it might just not be properly initialized (you're using an attribute to signal full initialization but what do you do with uninitialized objects besides removing them? In that case initialized should not be a property of the objects or wrappers themselves).
If you have such a high number of subclasses you might want to check what the differences are. It might be a more flexible approach to use composition instead of inheritance.
Example of the last point:
class Vehicle {
VehicleType type; //e.g. Aircraft, Boat, Car
Set<Features> features; //e.g. 2 wheels, 4 wheels, wings etc.
Behavior behavior; //Class to implement specific behavior, depending on your needs
}
class AircraftBehavior extends Behavior {
void fly() {
//implements flying mechanic
}
//method overridden/implemented from Behavior
#Override
void move() {
fly();
}
}
//create an aircraft
Vehicle aircraft = new Vehicle( VehicleType.AIRCRAFT, new HashSet<Feature>(new WingsFeature()), new AircraftBehavior());
The last part would also be predestined for using the factor or builder pattern.
When child class can not full fill the contract of constructor with parent class. Then at same place exists a design defect.
The issue/reason can be that the child class is not valid as a child class or the parent class has to many functionalities.
For your example is really hard to tell what is breaking the contract. But the best and most flexible thing to work with are interfaces.
You claim that you are not an expert in Java. Interfaces are just a concept in Object Oriented programming in case you look for any carrier in this area you should be familiar with them. SO this might the time for you to learn more about interfaces and software design.
Related
Can any body provide me a practical example/scenario where we make use of abstract class and abstract method in Java? An explanation with sample code would be of help in understanding it conceptually. Thanks
abstract class Car{
public int drivenKm;
//....
public abstract void checkCar();
}
public class Volvo extends Car {
public void checkCar() {
checkWithVolvoTestSpecs1();
}
//you have some Volvo-specific tests implemented here
public void checkWithVolvoTestSpecs1(){
//....
}
}
public class BMW extends Car {
public void checkCar() {
checkWithBMWTest();
}
//you have some BMW-specific tests implemented here
public void checkWithBmWTest(){
//....
}
}
Now you can have a list of Cars containing BMW's or Volvo's.
It sometimes makes no sense to implement a general checkCar()-method, because they need to be checked according to some producer-specific checks. So you should mark the class abstract as well as the method.
Marking the class abstract prevents you from generating a non specific car which can not be checked.
Marking the method abstract is used to not being forced to implement a general car check as well as forcing any derived classes to implement a specific car check.
This grantees that you can call the checkCar()-method for every object in your list of Cars because it is guaranteed that there is no general car object which has no implementation of checkCar() as well as that every specific object (like BMW) in the list has an implementation of that method.
public static void main() {
List<Car> cars = new ArrayList<Car>();
cars.add(new Volvo());
cars.add(new BMW());
foreach(Car c:cars)
c.checkCar();
}
So I'm having trouble wrapping my head around the proper design for this.
My application has two key objects that control state, that need to interact with one another: ItemList, ItemState. These each rely on a generic ITEM_TYPE so they can function in different contexts. They are also abstract to allow for ITEM_TYPE-dependent behavior.
Both pieces need to know the generic type, but moreover, since they talk to one another, they need to know the generic types of one another. (An ItemList< String > instance needs to know that its ItemState field is an ItemState< String > and vice versa).
My current solution works, but it seems awful. There has to be a better way. This is what I'm doing now:
public abstract class ItemState<
ITEM_TYPE,
STATE_TYPE extends ItemState<ITEM_TYPE, STATE_TYPE, LIST_TYPE>,
LIST_TYPE extends ItemList<ITEM_TYPE, STATE_TYPE, LIST_TYPE>> {
}
public abstract class ItemList<
ITEM_TYPE,
STATE_TYPE extends ItemState<ITEM_TYPE, STATE_TYPE, LIST_TYPE>,
LIST_TYPE extends ItemList<ITEM_TYPE, STATE_TYPE, LIST_TYPE>> {
}
Then an implementing class might look like:
class StringState extends ItemState<String, StringState, StringList> {
}
class StringList extends ItemList<String, StringState, StringList> {
}
Note that for ItemState, STATE_TYPE is a reference back to the implementing class, and likewise for ItemList/LIST_TYPE.
Really my problem would be solved if I just make ItemState an inner class of ItemList since there would be an implicit binding and they could share generic declarations, but both classes are so large and standalone, that I would prefer not to do this.
Any suggestions?
Edit: As a counter-example to a comment:
public abstract class ItemState<ITEM_TYPE> {
public abstract ItemList getItemList();
public void doSomething() {
// This should not compile because abstract super class has
// no idea what the generic type of getItemList() is
ITEM_TYPE item = this.getItemList.getItem();
}
}
Edit 2: I think the best solution I could think of was just to make ItemList/ItemState inherit one way or the other so they can function as the same class. I don't love this solution because it overrides separation of concerns, but it makes the generics a lot more manageable.
Sidenote: my actual applicaiton had this problem with 4 intertwined classes, I just used 2 for simplicity. In actuality the generics were so bad they were incomprehensible and hard to refactor (about 4 entire lines of just generic declarations for each class). I've now made these 4 classes into a vertical inheritance hierarchy
JM Yang's solution is pretty good
I think you may just reference to generic type ITEM_TYPE when declaring these 2 classes.
I'm able to compile below code with no errors.
public abstract class ItemList<ITEM_TYPE> {
public abstract ItemState<ITEM_TYPE> getState();
public abstract ITEM_TYPE getItem();
}
public abstract class ItemState<ITEM_TYPE> {
public abstract ItemList<ITEM_TYPE> getItemList();
public void doSomething() {
ITEM_TYPE item = getItemList().getItem();
System.out.println(item);
}
}
public class StringList extends ItemList<String> {
#Override
public StringState getState() {
return new StringState();
}
#Override
public String getItem() {
return "";
}
}
public class StringState extends ItemState<String> {
#Override
public StringList getItemList() {
return new StringList();
}
}
I have a class called Car, and an extention of Car, called Mazdamx5. Can I create a class that extends Mazdamx5 that contains the properties of Car, but also contains the modified or overridden properties of Mazdamx5, or will this only cause complications? Oh, yeah, forgot the important part. How do I do all this with Car and Mazdamx5 in a different package than my new extention? By import?
You can certainly have class hierarchies like this, but you should consider your design implications a bit closer. Having deeply nested inheritance like that isn't necessary in a lot of cases.
If you want each class to have shared fields, then use protected instead of private for their declaration.
This is entirely legal:
public class Car {
}
public class Mazdamx5 extends Car {
}
public class SomeOtherCar extends Mazdamx5 {
}
Try it out. Perfectly valid to create another class that extends Mazdamx5.
I provide the code example
class Car{
void carDrive() {
S.O.P("car drive");
}
}
class Mazdamx5 extends Car{
void drive() {
S.O.P("drive 2");
}
}
class Car2 extends Mazdamx5 {
void drive() {
S.O.P("Car 2 drive");
}
}
In this case, this class Car2 extends Mazdamx5, overrides method properties of Mazdamx5(drive method), and contins method properties of car(carDrive)
I've to create a simple self-made ActiveRecord class for my project.
Only stuck on the problem that I have a getModel() in my Player class, which is being extended by a ActiveRecord class.
When I want to use the getModel() method from my ActiveRecord class, I cant use it cause it's not the same type. I don't want to reference Player here, because I want to use multiple models.
Anyone has a solution?
Ok so I got something up:
abstract class ActiveRecord<T> {
private T model;
public T getModel() {
return this.model;
}
}
public class Player extends ActiveRecord<Player> {
}
public class Event extends ActiveRecord<Event> {
}
But when I try to output this.model in my ActiveRecord class, it return null.
What is wrong here?
Your method definition needs to do something like this
public Class<? extends ActiveRecord> getModel();
Meaning of this is that the return type is of class that extends ActiveRecord. When you do this to the child it would return Player.class as Player extends ActiveRecord.
A brief note if getModel return an object of that class then you should remove Class from the method function
public <? extends ActiveRecord> getModel();
So if I understand well you have a super class called ActiveRecord and a subclass Player, which has a method getModel.
If you want to use ActiveRecord as reference type then you need to have a getModel method in that class as well if you want to access that method. If you are never going to instantiate an ActiveRecord as such you can make it abstract and define the getModel method abstract. If you don't have any implementation logic in ActiveRecord you could make it an interface as well.
public abstract class ActiveRecord {
public abstract Model getModel();
}
public class Player extends ActiveRecord {
#Override
public Model getModel() {
...
}
}
You're making life way too hard for yourself. Java already does reflection for you.
class Parent {
// class content
}
class ChildA extends Parent {
// class content
}
class ChildB extends Parent {
// class content
}
Parent firstInstance = new ChildA();
Parent secondInstance = new ChildB();
Class typeOfFirst = firstInstance.getClass();
Class typeOfSecond = secondInstance.getClass();
As for your null pointer error, in Java (Unlike c++ for example) you have to explicitly initialise every variable with new. Just having private T model; doesn't create an instance of it.
Okay, so, for example, let's say I have an abstract class called "Vehicle". The Vehicle class, has, among other things, a static variable called wheels, which is not initialized. What I want to do is have other subclasses extending from the Vehicle class, like "Motorcycle", and "Truck", and in these subclasses, have the wheels initialized.
Code:
public abstract class Vehicle {
static int wheels; //number of wheels on the vehicle
}
But the below doesn't work:
public class Motorcycle extends Vehicle {
wheels = 2;
}
Is there a way to do this effectively?
EDIT:
Thank you to all the people who replied so far. I get that making instances is probably a better way to go than to put them all in separate classes, but I don't get the "static" part of java perfectly, so I need a little help here.
What I'm trying to do for my program is have separate sprites for the Motorcycle and Truck classes, and I want them to be static so that I won't have to reload the image every time I create an instance of a Motorcycle or Truck. Other than that, though, they'll have almost identical properties to each other, which is why they'll both be extending from the Vehicle superclass.
The only other way I can see this being done is by just not declaring the sprite variable at the Vehicle class, but at the Motorcycle/Truck class, like below:
public abstract class Vehicle {
//Other coding
}
public class Motorcycle extends Vehicle {
static BufferedImage sprite = //initialize image
//Other coding
}
public class Truck extends Vehicle {
static BufferedImage sprite = //initialize image
//Other coding
}
If 'wheels' is static, there is only one and it will apply to all vehicles at the same time. So tricycle, a motorcycle, an 18-wheeler truck and a Ford will all have the same number of wheels.
That doesn't make sense to me. It would be better to have 'wheels' be an instance variable that is in the parent class but each subclass sets appropriately.
But you can try
Vehicle.wheels = 2;
NOTE: I'm adding to my answer since you added to your question.
I like your idea of having statics in each of the subclasses. But you should make them private. Then put an abstract method in the parent class (Vehicle) like
public abstract BufferedImage getSprite();
Then each direct subclass has to have the same method and it can return the private static variable.
Make the variable static so you only have to load them once. Make them private so that code outside the class itself can't fool with it and introduce bugs. You could make them 'final' if possible so the code in the class itself can't change it after the fact and introduce bugs. (A 'final' variable can't have its value changed but the contents of its value can change. So 'final' isn't a wonderful as it could be.)
What you're trying to do is fundamentally flawed. You could make Motorcycle initialize wheels once:
// Static initializer
static
{
wheels = 2;
}
... or each time an instance was created:
// Instance initializer
{
wheels = 2;
}
But there's just one variable - not one for Motorcycle, one for Truck etc. If you did the same thing for both Truck and Motorcycle, then whichever is initialized last would "win".
It's not clear how you want to use this field anyway - but if you just have a single static field, then that's just going to have a single value - not one per subclass.
Static members are only defined once and are common to every extending class. Changing the value in one of them will affect all of the others.
This is what I believe you really want to achieve:
public abstract class Vehicle {
private int _wheels; //number of wheels on the vehicle
public int getWheels(){return _wheels;}
protected Vehicle(int wheels){
_wheels = wheels;
}
}
public class Motorcycle extends Vehicle {
public Motorcycle(){
super(2);
}
}
public class Car extends Vehicle {
public Car(){
super(4);
}
}
I think there's a significantly more elegant way to do this
What I am about to propose still suffers from the limitation that you need an instance. I don't see any way around that because you want wheels to be exposed as part of the superclass, but the value of wheels is dependent on the subclass and inside of Vehicle there is no notion of a subclass type without an instance.
In my opinion, 'wheels'in this case is neither a static or non-static property. It is class metadata. And the Java way to specify class metadata is via annotations.
What you need is a user-defined annotation like this:
#Documented
#Retention(RetentionPolicy.RUNTIME)
public #interface VehicleMetadata{
int wheels();
}
You then annotate Motorcyle as follows:
#VehicleMetadata(2)
public class Motorcycle extends Vehicle {}
In the superclass you provide an accessor that gets the value of the annotation property. I would recommend you use a "lazy evaluation" approach so you don't use reflection every time you need the value.
Note the use of this to get the instance:
private String wheelsValue;
public String getWheels() {
if (this.wheelsValue== null) {
VehicleMetadatane = null;
for (Annotation annotation : this.getClass().getAnnotations()) {
if (annotation instanceof VehicleMetadata) {
ne = (VehicleMetadata) annotation;
break;
}
}
wheelsValue = ne.wheels();
}
return wheelsValue ;
}
In my opinion, this is the most elegant solution.
The original class declaration:
public abstract class Vehicle {
static int wheels; //number of wheels on the vehicle
}
public class Motorcycle extends Vehicle{...}
public class Truck extends Vehicle{...}
does not work because the static variable goes with the class it was declared in. Static class variables create memory storage for only one instance of the variable per class and not per class object. When the compiler (jvm) sees the static variable in the class Vehicle it allocates memory to that variable and that memory location is static (does not change). Each subsequent use of the Vehicle class whether it is extended or instantiated as an object will point to the same location in memory for the static variable.
In order to use the static variable in the child classes you have to use it inside a method. So, you could in essence re-write your Motorcycle class like this:
class Motorcycle extends Vehicle{
public Motorcycle(){
wheels = 2;
}
}
and it will compile; however, you will may not get the results you expect. For example if you do this in your code (assuming Truck class is declared like Motorcycle class and assigns 4 to wheels and there is a getter method to return the value of wheels).
Motorcycle cycle = new Motorcycle();
Truck pickup = new Truck();
...
System.out.println("Motorcycle has " + cycle.getWheels() + " wheels.");
will print:
Motorcycle has 4 wheels.
If you make a static variable in your objects it will be the same for every Vehicle class you will make, even when you would make another subclass for your abstract Vehicle class. This because of the "nature" of any static variable.
I think you want to use a non-static variable so that for every instance of any subclass of the abstract Vehicle class you can determine the value of the wheels and that is done as following:
public abstract class Vehicle {
public int wheels; //number of wheels on the vehicle
}
and any subclass:
public foo extends Vehicle{
public void someMethode(){
this.wheels = 2;
}
}
You could also do this for the static variable but then you will change it for every instance of any subclass of Vehicle
Hope i helped you
Maybe you'd like to think about the constructors you are using.
public Vehicle(int wheels) {
this.wheels = wheels;
}
public Motorcycle(int wheels) {
super(wheels);
}
public Motorcycle cycle = new Motorcycle(2);
The Motorcycle uses the super constructor that knows what to do with the parameter. It automatically sets wheels to 2.