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);
// ...
}
Related
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.
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.
public abstract class Test {
private static int value = 100;
}
And
public abstract class Test {
private int value = 100;
}
Since Test is abstract, it can't be instantiated, and therefore it doesn't make any difference whether value is static or not, right?
Is there any difference when a field is static or not when it belongs to an abstract class?
Yes, there is. Even thou your class is abstract, it can have non-abstract non-static methods working with non-static private fields. It is usefull sometimes.
Dummy exaple:
Consider following: you want to hold one integer and give everyone the ability to change it, but you dont want them to set negative values, or values bigger then 15, but the condition isn't known (in general) by everyone, so you want to ensure that when someone sets incorect value, it gets fixed automaticly.
Here is one possible solution:
abstract class MyInt {
private int myInt;
public int getMyInt() {
return myInt;
}
public void setMyInt(int i) {
myInt = checkMyInt(i);
}
protected abstract int checkMyInt(int i);
}
Now you can inplement any logic in checkMyInt() and hand over the instance declared as MyInt
pastebin exaplme
PS: this probably isnt the best solution and i would use interfaces here, but as an example it is enought i hope
Abstract classes can't be instantiated directly. But the whole point of abstract classes is to have subclasses that are instantiated:
public abstract class Test
protected int value;
}
public class TestImpl extends Test {
public TestImpl(int value) {
this.value = value;
}
}
In the above example, each instance of TestImpl (and thus of Test) has its own value. With a static field, the field is scoped to the Test class, and shared by all instances.
The difference between static and non-static fields is thus exactly the same as with any other non-abstract class.
An abstract class is a normal (base) class, just declared to be missing some things, like abstract methods.
So there is definite a difference.
I know there have been lots of thread about Java inheritance (and i already read it), but they all stand for "how it is", and I need knowledge "how to change it". So, we have 2 classes:
class t1{
public int a=5;
public void get(){
System.out.println(a);
}
}
class t2 extends t1{
public int a = 1;
}
and now :
t2 z = new t2();
z.get();
And we get 5
Of cource it is just example, but what i want to do is make some common methods in superclass which will use field from inherited class, ex. user messages
Is there any way to do this? If not then why i would use superclasses, can i use anything else?
Thanks in advance
You should use a constructor and possibly a getter
class t1{
public final int a;
public t1() {
this(5);
}
protected t1(int a) {
this.a = a;
}
public void get(){
System.out.println(a);
}
}
class t2 extends t1{
public t2() {
super(1);
}
}
now
t2 z = new t2();
z.get();
prints 1
Yes, there is a way do to this. You can apply pattern which called "Template method". Here is an example
class Base {
void someMethod() {
int value = getValue();
// calculate something
}
protected abstract int getValue();
}
class Derived extends Base {
int getValue() {
return 5;
}
}
Where getValue() is your template method and you can insert any logic in your inherited classes implementations.
you are shadowing/hiding the variable of t1!
t1 can see the variable of t2 and prints it's own a-value in the get method.
you don't need to declare a again because the a of t1 can be seen everywhere
if you want another default value for a in object of type t2 override the default constructor.
public t2() {
this.a = 1;
}
Polymorphism works only for methods, not for fields and you cant change this Java mechanism. It means that late binding will find correct body of method depending on class of object
class X{
void sayHello(){
System.out.println("Hello from X");
}
}
class Y extends X{
void sayHello(){
System.out.println("Hello from X");
}
}
//...
X obj = new Y();
obj.sayHello();// even if you are using X reference body of method will
// come from Y class
But fields are not polymorphic so if method uses some field it will use this field all the time (once again, late binding will not search for newest field declared in class of current object). That is why you are seeing 5 as result.
If you want to simulate" polymorphic behaviour of field used in methods body your best choice is to let derived class set new value of that field in base class like in Peter Lawrey's answer (big +1 for him).
I have a super class 'BuildingMaterial' and loads of subclasses, i.e. Stone, Wood, Clay, etc.
All subclasses behave similarly: 1 int field that stores the amount of a building material in units. They can be constructed parameterless or with an int. I already know that ALL subclasses of BuildingMaterial will have these two constructors, how do I avoid coding them into every single class?
Here's an example of what I don't want to do in every class:
public final class Stone extends BuildingMaterial {
private int amount;
//constructors
public Stone() {
amount = 0;
}
public Stone(int i) {
amount = i;
}
//methods
public int getAmount() {
return amount;
}
}
Sadly, the answer is you can't. This is a limitation of the Java language. Each class needs its own constructors—you can't simply inherit them from a parent class. The only constructor the Java compiler will generate for you is the default constructor (no arguments), and it only generates that if you don't specify any constructors at all.
The best you can do here is to refactor your code so amount is in the superclass:
public abstract class BuildingMaterial {
private int amount;
//constructors
public BuildingMaterial() {
this(0);
}
public BuildingMaterial(int i) {
amount = i;
}
//methods
public int getAmount() {
return amount;
}
}
And then make use of super calls to delegate the superclass's constructor in your subclasses:
public final class Stone extends BuildingMaterial {
//constructors
public Stone() {
super();
}
public Stone(int i) {
super(i);
}
}
Note that I changed the body of your no-argument constructor from amount=0; to this(0);. I personally think this is better style because, if you decide to add other initialization code to your constructor body, you only have to add it to the 1-argument constructor, and the zero-argument constructor will just delegate all the work to it.
You have to use inheritance
public abstract class BuildingMaterial {
private int amount;
//constructors
public BuildingMaterial() {
amount = 0;
}
public BuildingMaterial(int i) {
amount = i;
}
//methods
public int getAmount() {
return amount;
}
}
public class Stone extends BuildingMaterial {
public Stone() {
super();
}
public Stone(int i) {
super(i);
}
}
This way all subclasses of BuildingMaterial can give access to amount through getters and setters.
You may have amount declared as protected so you wont need getters or setters to access that field inside subclasses.
use super keyword to reduce your code but the super is to be the first line inside the constructor
public class Stone extends BuildingMaterial {
public Stone() {
super();
}
public Stone(int i) {
super(i);
}
}
If all classes has the attribute amount, then that attribute can be inherited from parent. Define amount in your parent class BuildingMaterial and then call the parent constructor from your child classes constructors using super to set the amount value.
Its unclear what you want to avoid in your question... assuming you are talking about avoiding writing multiple constructors in all the subclass. I believe its not possible to do so. below post of defining BuildingMeterial constructor and calling the super() from baseClass will be the best solution to use.