Avoiding code duplication with Java abstract methods - java

I have a class (let's say Vehicle) with a rather large number of subclasses (Car, Bike, ..). Every subclass stores specific information on the type of the subclass (# of tires, ..).
I want to ensure that all this information is already enforced (at compile-time).
So I don't want to specify this data in the constructor of the subclass (because I might forget to set some of them). I could put this info in the constructor of Vehicle, but this would clutter code quite a lot, since I have many of those parameters.
public class Vehicle {
int numberOfTires;
public Vehicle(int numberOfTires, ...) {
...
}
}
public class Bike {
public Bike() {
super(2,...);
...
}
}
I end up with completely unreadable constructors. It would also store this info per instance, even though it is specific to the subclass.
An alternative way is to introduce abstract static getters/setters and store the info in the subclasses.
public class Vehicle {
...
abstract public int getNumberOfTires();
}
public class Bike {
static int numberofTires = 2;
...
public int getNumberOfTires() {
return numberOfTires;
}
}
This seems way cleaner and also stores the info per subclass and not per instance but there will be a lot of code duplication in the subclasses. Right now, all the subclasses contain ~20 setters/getters but virtually no real functionality. Is there a clean way of avoiding this? Perhaps using the Factory method or alike?

In your shoes, I'd do it this way
public abstract class Vehicle {
public abstract int getNumberOfTires();
}
and
public class Bike extends Vehicle {
#Override
public int getNumberOfTires() {
return 2;
}
}
and
public class Car extends Vehicle {
#Override
public int getNumberOfTires() {
return 4;
}
}

You should put in your Vehicule class everything that is common. If the number of tires is a common attribute of all your Vehicule, than it belongs there.
Using the factory pattern you could avoid having to write each time you want a instance of a Bike all that is needed in the Vehicule class as the factory would do that. Meaning the code that sets the parameters of a Bike is written in one place, the BikeFactory class.
That would make the line creating a Bike looks like
Bike yourBike = BikeFactory.getInstance().create();
instead of
Bike yourBike = new Bike(numberOfTires, ... );
The factory would have either a line that looks like the above one or a bunch of calls to setters. I would recommend you use setters and just a new Bike() constructor without parameter.
The naming of the factory, methods and the factory being a singleton are only as example and can be implemented as you see fit in your application.
As mentionned, you could also use another class for the parameters but that only move the hassle of settings your parameters somewhere else.

Seems to me that what you are talking about here are constants, e.g. values that are not supposed to change at runtime. In Java, constants are variables with the following qualifiers: static final, along with private/public. Then, you won't need setters, since a Bike will never anything other than 2 wheels for instance.
I don't really see the problem with having lots of getters and setters, your Bike-class has a set of properties describing it, and they are all needed. So something like:
public abstract class Vehicle {
public abstract int numberOfTires();
public abstract boolean hasEngine();
}
public class Bike extends Vehicle {
private static final int NUMBER_OF_TIRES = 2;
private static final boolean HAS_ENGINE = false;
public int numberOfTires() {
return NUMBER_OF_TIRES;
}
public boolean hasEngine() {
return HAS_ENGINE;
}
}
These variables are properties of the entity that you are representing, and as per object-oriented principles, they belong as members of the class.
All domain classes will have a number of variables, and in most cases they will require at least a getter, there is no way around this. Still, it is good to keep your domain classes as small as possible, not necessarily with regards to lines of code, concepts it represents. If a domain class has grown large, decompose it and group variables that belong together is separate classes. Then each of the smaller classes will have a constructor with a limited amount of variables, and instance creation
If all that matters in limiting the amount of code in your subclasses you could do something like the code below. I'm not sure if I would recommend it though, and I don't think I'd do this in practice.
public abstract class VehicleInfo {
public abstract int numberOfWheels();
}
public class BikeInfo extends VehicleInfo {
#Override
public int numberOfWheels() {
return 2;
}
}
public class CarInfo extends VehicleInfo {
#Override
public int numberOfWheels() {
return 4;
}
}
public class Vehicle {
final VehicleInfo info;
Vehicle(final VehicleInfo info) {
this.info = info;
}
public int numberOfWheels() {
return info.numberOfWheels();
}
}
public class Bike extends Vehicle {
public Bike() {
super(new BikeInfo());
}
}
public class Car extends Vehicle {
public Car() {
super(new CarInfo());
}
}
This way all getters are located in the superclass (as well as in the info-classes), and the subclasses can stay clean.

Related

Java - Is it possible to extend all the subclasses of a class with a single class?

Java - Is it possible to extend all the subclasses of a class with a single class?
Let's explain it with an example, the actual code is quite more complex. I have an Animal class with its own class hierarchy. Let's say that it has two subclasses: Testarrosa and Viper.
public class Car {
public abstract String getManufacturer();
}
public class Testarossa extends Car{
public String getManufacturer(){
return "Ferrari";
}
}
public class Viper extends Car{
public String getManufacturer(){
return "Dodge";
}
}
I want to extend all the Car subclasses with a RegisteredCar subclass.
public class RegisteredCar extends Car {
private String plateNumber;
public RegisteredCar (String plateNumber){
this.plateNumber=plateNumber;
}
public String getPlateNumber() {
return plateNumber;
}
}
At some point, I should be able to create a new RegisteredCar of a specific subclass. Something like
RegisteredCar c = new RegisteredCar<Viper>("B-3956-AC");
And call the c.getManufacturer() to obtain "Dodge" and c.getPlateNumber() to obtain B-3956-AC. Obviously, I should still be able to create a Car c = new Viper();
That is an example. Having an attribute in Car with null value if not registered is not enough for what I need.
In short, no that is not possible. You have to unfortunately modify your object model.
For example, what about having a Registration class this way:
public interface Registration<C extends Car> {
C getCar();
String getPlateNumber();
}
This way you can extract the information relating to registration in a single class, while maintaining your Car models.
You can then do helper methods like:
Registration<Viper> registeredViper = createRegistration(new Viper(), "B-3956-AC");
As others have said, no thats not really possible and your example could be solved by changing your model
As an alternative to inheritance you could use another class to wrap a Car instance.
I would make Car an interface (though having RegisteredCar extend Car should work too) and then attempt something like the following pseudo code:
class RegisteredCar<T extends Car> implements Car {
private final T car
RegisteredCar(T car) {
this.car = car;
}
... methods for RegisteredCar
... methods from Car delegating to `this.car`
}
Please excuse the somewhat bad code, I don't have an IDE open, and I always mess up generics without an IDE to hand.
Another possible solution is to use AOP, though I don't know how in fashion that is these days as but what you are describing could be a cross cutting concern.
A final alternative might be to use a language that allows for Extensions, Traits, Protocol or some other type of 'mix in'
In java it is prohibited to extends more than 1 class.
You could build chain from classes to extends, for example.
To solve the problem of mutiple inheritance in Java → interface is used
You should avoid inheritance as much as possible. Use abstractions (interfaces) to make your code elegant and maintainable. Just google why extends is evil.
public interface Car{
String getManufacturer();
}
public interface Registerable{
boolean isRegistered();
void register(String plateNumber);
void getPlateNumber();
}
public class Viper implements Car, Registerable
{
//all methods
}
With Generic class approach as described in other answer, you will not be able to use RegisteredCar where your require to pass Car object. e.g. suppose you need to generate some invoice.
Invoice getInvoice(Car c);
In this method you cannot use RegisteredCar as it is not of Type Car. All you API which require Car are not applicable to RegisteredCar. In some cases you may need Plate Number as well as Car, There you may need to keep mapping of Plate Number and Cars. I would suggest following approach based on Decorate Pattern and delegate all Car calls to passed car object
public class RegisteredCar extends Car{
public RegisteredCar(Car c, String plateNumber){
}
#Override
String getColor(){
c.getColor();
}
}
No, it's not like C++. Multiple inheritance is not possible in Java. However you can implement multiple interfaces.
You cannot achieve that with inheritance.
Your best option is making the RegisteredCar type generic, then having a generic instance variable that holds the intended type car:
public class RegisteredCar<T extends Car> {
private String plateNumber;
private T car;
public T getCar() {
return this.car;
}
public T setCar(T car) {
this.car = car;
}
public RegisteredCar (String plateNumber){
this.plateNumber=plateNumber;
}
public String getPlateNumber() {
return plateNumber;
}
}
With this, you will be able to pass into RegisteredCar an object of any type that's a subclass of Car.
As you can notice, I have removed the extends Car part of this class, as it doesn't need to be a subclass of car itself.
Is there a reason, in the real classes, that you couldn't simply add the new feature to the existing base class?
public abstract class Car
{
public abstract String getManufacturer() ;
protected String plate_number = null ;
public String getPlateNumber()
{ return this.plate_number ; }
public boolean isRegistered()
{ return ( this.plate_number != null ) ; }
}

Java interface classes?

So, I am trying to learn how the interface classes in Java Work, and i'm really confused about it.
I wan't to make it like a method in a normal class file like this:
public class APIClass {
private int davs;
public int setInt(int dav) {
this.davs = dav;
return davs;
}
public int getInt() {
return davs;
}
}
Two methods. One that set's the int "davs", and one getting the int "davs".
What i wan't to do in the interface is something like that. I have seen in others interface files, that they have something like this:
public interface MyInterface {
public MyInterface setInt(int davs);
public MyInterface getInt();
}
EDIT:
My question is that i can't see what i can use the interface for? All i have seen use it, declare the same method in a new class file, and then they really don't need the interface file. So what is it for?
Interfaces in Java are meant as an abstraction. You're expected to use it strictly for deriving other classes. You don't declare any methods in it all.
So if you have an interface like this:
public interface MyInterface {
int setInt(int davs); // this should probably return void
int getInt();
}
And you implement it in a class like this:
public class APIClass implements MyInterface {
private int da;
public int setInt(int davs) {
// return da; <- this doesn't make a whole lot of sense
da = davs; // I assume you meant this
return da; // usually you don't return anything from a setter
}
public int getInt() {
return dada;
}
}
And another class like this:
public class SecondAPIClass implements MyInterface {
private int dada = 0;
public int setInt(int davs) { // note that you have to keep the same method signiture in all derived classes
dada = davs + 5;
return dada;
}
public int getInt() {
return da;
}
}
You can use the interface to group them both. This is an important part of object oriented design. It's usefulness is probably too long to explain in a simple StackOverflow question, but here's a simple example of its usefullness:
import java.util.ArrayList;
public static void main(String[] args)
{
APIClass first = new APIClass();
SecondAPIClass second = new SecondAPIClass();
first.setInt(20);
second.setInt(20);
ArrayList<MyInterface> list = new ArrayList<MyInterface>();
list.add(first);
list.add(second);
for(MyInterface item : list) {
System.out.println(item.getInt());
}
}
The output should be this:
20
25
This example might be more helpful:
Consider you have several vehicles. All vehicles can drive, but driving a boat is different from driving a car, or a helicopter. This is where interfaces are useful. You can declare what a Vehicle should do, without dictating how it should do it.
public interface Vehicle {
void drive();
}
So when you derive it in a class Car, you can state how you want this vehicle to drive.
public class Car implements Vehicle {
void drive() {
// drive like a car
}
}
Now boats are vehicles, and they can drive too, but driving a boat is much different than driving a car.
public class Boat implements Vehicle {
public void drive() {
// drive like a boat
}
}
In summary, interfaces are useful when you have an abstract concept in mind, where you know what derived objects should do but can't dictate how they do it.

JAVA Inheriting static field from base class in the way that it will differ for every subclass

I have a base class
public class base
{
//some stuff
}
and several subclasses
public class sub1 extends base
{
static int variable;
}
public class sub2 extends base
{
static int variable;
}
etc
The static int variable exists in every subclass because I store in it information that is characteristic for every subclass. But it would be better if there was a way to move static int variable to base class in the way that it still will be different for every subclass.
In the way that it is now I am repeating myself, when adding some another subclass, it's a bad practice.
So anyone has some idea how to acomplish this? Maybe there's a design pattern that fits to this situation?
You cannot move all the different static variables from derived classes into the base class, because static variables are one-per-class; you want your variables to be one-per-subclass, which is not allowed.
You could work around this issue by defining a registry of subclasses in your base class, and store the int for each subclass there. However, this would add a lot more complexity, and it is not clear how you would differentiate between subclasses in the superclass.
Your current solution appears optimal.
Don't use a static field for this - that's not the way to go, because static fields of a subclass do not "override" those of a super class.
Instead, because the values are constant for a given class, use a final instance field:
public class Base {
protected final int variable;
public Base() {
this(5);
}
protected Base(int v) {
variable = v;
}
}
public class Sub1 extends Base {
private static int v = 7;
public Sub1() {
super(v);
}
}
Now the variable is fixed and accessible to all instances.
You can certainly move variable into the base class, but it cannot be static. Alternatively, you can make static getters which you override in each subclass. Here is an example of both:
public class base {
protected int variable;
protected static int getVariable() {
return -1;
}
}
public class Sub1 extends base {
public Base() {
variable = 0;
}
protected static int getVariable() {
return 0;
}
}
public class Sub2 extends base {
public Sub2() {
variable = 1;
}
protected static int getVariable() {
return 1;
}
}
As a design principle, it is somewhat rare (in my opinion) that you genuinely want static methods. Usually you will have some instance of the class around that you are working with. If you want a whole bunch of objects to share some common behavior which you configure at runtime, you might want to check out the flyweight pattern.

Which arguments for superclass constructor?

I'm studying a chapter in java related to Inheritance, and i have a few questions.
I' have basic understanding how inheritance works ( overriding methods, information hiding, how to use private fields from superclass in a subclass etc ), but i have just one problem and i hope you might help me.
When superclass have non default constructor(s) - without parameters, that means that in a subclass i have to create new constructor (it can be default - without parameters ), but in a first statement must be superclass constructor call.
Ok, so far so good. I understand so far. In subclass you must call superclass constructor, matching any of constructors parameters.
But lets check following code: (Superclass)
public class Vehicle {
private int numOfWheels;
private double avgGallonsPerMile;
public Vehicle(int numOfWheels, double avgGallonsPerMile) {
this.numOfWheels = numOfWheels;
this.avgGallonsPerMile = avgGallonsPerMile;
}
}
And another Subclass code:
public class Car extends Vehicle{
public Car(double avgGallonsPerMile) {
super(What should i write here?, avgGallonsPerMile);
//force numOfWheels to 4;
}
}
Here is the exercise for subclass:
Each subclass
contains a constructor that accepts the miles-per-gallon value as an argument and
forces the number of wheels to the appropriate value—2 for a MotorCycle and 4 for
a Car.
In subclass constructor i don't need numOfWheels field, because i will force it to 4 ( for car ) and 2(for motorbike) anyway.
But stil i need that data for superclass anyway. Where to get that data? What should as first parameter in call to superclass constructor.
But still this isn't the lonely case. I got lots of exercises that i don't need certain data in subclass constructor as parameters, BUT still i need them in superclass constructor call.
What should i do in such cases ?
I really hope you understood me, what i want to tell. It's kinda difficult.
If its anyway the same 4 for cars and 2 for motorcycles than make if fix!
super(4, avgGallonsPerMile);
or the better way - declare a constant:
private static final int NUM_OF_WHEELS = 4;
..
super(Car.NUM_OF_WHEELS, avgGallonsPerMile);
If you don't need a field in a super class then chances are it shouldn't be there. Instead you can do the following.
public abstract class Vehicle {
private final double avgGallonsPerMile;
public Vehicle(double avgGallonsPerMile) {
this.avgGallonsPerMile = avgGallonsPerMile;
}
public double getAvgGallonsPerMile() { return avgGallonsPerMile; }
public abstract int getNumOfWheels();
}
public class Car extends Vehicle{
public Car(double avgGallonsPerMile) {
super(avgGallonsPerMile);
}
public int getNumOfWheels() { return 4; }
}
public class Bicycle extends Vehicle{
public Bicycle (double avgGallonsPerMile) {
super(avgGallonsPerMile);
}
public int getNumOfWheels() { return 2; }
}
public class Tricycle extends Vehicle{
public Tricycle (double avgGallonsPerMile) {
super(avgGallonsPerMile);
}
public int getNumOfWheels() { return 3; }
}
BTW: Your car must be really inefficient if it uses gallons per mile of fuel.
Very simple: if the number of wheels on a Car is always 4, them simply pass the value 4:
public Car(double avgGallonsPerMile) {
super(4, avgGallonsPerMile);
// ...
}

Why do we need constructors and private members in the abstract class?

Why do we need constructors and private members in the abstract class? It is not like we are ever going to create an instance of that class.
You will create instances, just instances of a derived class. Those derived classes will still need to call constructors, and can still call members of the abstract class - which may in turn use private members.
Here's an example (not a terribly useful one, but just to show the basic idea...)
public abstract class NamedObject
{
private final String name = name;
protected NamedObject(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
public class Computer extends NamedObject
{
private final int processorSpeed;
public Computer(String name, int processorSpeed)
{
super(name); // See, the constructor is useful
this.processorSpeed = processorSpeed;
}
public String toString()
{
return getName() + " (" + processorSpeed + ")";
}
}
I can't say I write abstract classes that often, generally preferring composition to inheritance, but when I do create them I certainly use constructors and private members.
Abstract classes provide a partial implementation of some interface. It's perfectly reasonable to consider that you might want to provide part of that implementation and disallow client code (concrete subclasses) from accessing the specifics - i.e. an extension of the principle of encapsulation.
Marking some members as private forces the inheriting class to call protected methods to access that partial implementation; providing a constructor allows for subclasses to initialise the parent's encapsulated state during their own construction.
Unlike an interface, an abstract class that defines data fields is in fact instantiated in the sense that these data fields are allocated. It is just that they are never instantiated on their own, they are instantiated as part of something bigger - the subclass. So when the subclass is built, the supertype is built as well, which is why you would need a constructor.
Depending on your hierarchy, your abstract class may have a meaning and state. For example, if your application is a school you may have the notion of a person (that has a name and an SSN), but you would have different subtypes for students and for faculty. Because both types of people share certain state structure (name and SSN) you would have both classes extend the Person class. But you would never simply instantiate a person directly.
In addition to Jon's answer, I'd like to mention that abstract classes still go well with composition, if you keep the subclass tree shallow. I.e. it is great for providing a common base class for a few closely related objects, but not for creating a gigantic tree of subclasses.
Why do you need private class? I think that you are confusing abstract classes with interfaces. Unlike interfaces, abstract classes can hold functionality. For example:
public class AbstractBase{
private int num;
public AbstractBase(int number){
this->num = number;
}
public int method(){
return ( this->num * this->templateMethod());
}
public abstract int templateMethod();
}
public class ConcreteDerived extends AbstractBase{
public ConcreteDerived(){
super(4);
}
public int templateMethod(){
return number; //number is the result of some calculation
}
}
In this example, you´ll never explicitly instantiate AbstractBase, but by declaring members and constructors, you can customize the functionality of your classes (this is called template method).
Assuming you're doing ad hoc code or prototyping, you do instantiate abstract classes (or maybe even interfaces) from time to time. They're called anonymous inner classes (one, two) and look like this:
// you have this...
public abstract class SomeClass {
public abstract String returnAString();
}
// ...and this...
public class OtherClass {
public void operate(SomeClass c) {
System.out.println(c.returnAString());
}
}
// ...so you do this:
OtherClass oc = new OtherClass();
// this is one of the reasons why you need to specify a constructor
oc.operate(new SomeClass() {
#Override
public String returnAString() {
return "I'm an anonymous inner class!";
}
});
This example is of course quite redundant but should expose the point. Some existing frameworks even rely on the heavy usage of this behaviour, namely Apache Wicket at least.

Categories

Resources