Inheritance and methods - java

I'm having a problem with the constructors of classes and sub-classes(that extend the first class)
This is the basic class's constructor:
public Airplane(int x, int y, int width)
{
this.x = x;
this.y = y;
this.width = width;
createSeats();
}
And here is another class's constructor that extends the basic class
public Boeing(int x, int y, int width)
{
super(x,y,width);
createSeats();
}
The problem is that createSeats() is another method in both classes, but Boeing has to override the main one. How can I make it so that this will work without taking the createSeats() method out?

If you know you want all subclasses of Airplane to call createSeats() on construction then you can leave the call in the Airplane constructor and remove from Boeing.
If you only want particular subclasses, e.g. Boeing to call createSeats() on construction then you can leave the call in the Boeing constructor and remove from Airplane.
You don't need the invocations in both constructors, leaving them there will result in createSeats() being called twice for each Boeing you initialise.

The call to the super constructor already includes the call to the createSeats() method, so you don't have to reinclude it in the Boeing constructor.
If you only want to change the behavior of creating seats, just override that method.
class Airplane {
public Airplane(int x, int y, int width)
{
this.x = x;
this.y = y;
this.width = width;
createSeats();
}
void createSeats() { /* create them */ }
}
class Boeing {
public Boeing(int x, int y, int width)
{
super(x,y,width); // same steps as super class
}
#Override
void createSeats()
{
// do something else entirely
// possibly call super.createSeats()
}
}

Frequently a default implementation of a method is provided in a super class, which allows you to customize the behavior in a subclass by overriding the method in a subclass. E.g. Does an Airplane know how to create seats on a Boeing? Probably not, therefore you would override the createSeats() in your subclass to provide the specific implementation that works for you particular type of Airplane.
The fact that the createSeats() method is called from inside your super class' constructor guarantees that the method in question will always be called on construction of the object. This is a common design pattern. It's called template method. Basically you have a method that encapsulates the execution of a number of methods in a certain order to produce an outcome. In your case there's one method namely createSeats().

I agree with #milkplusvellocet's answer, however you also said "The problem is that createSeats() is another method in both classes, but Boeing has to override the main one." If you ever need to call a superclass's method instead of your own, you can always call super.createSeats(). That way you can always differentiate between methods in the superclass and your own methods.
However, that said, that's almost always used in the method you're overriding. For example,
#Override
public void createSeats() {
doSomethingSpecial();
super.createSeats();
}

#Override
before the method you want to override should do the job

Related

Multiple Super( ) for overloading super class constructor

class Time
{
public static void main (String args[])
{
Son obj = new Son();
}
}
class Father // Super Class
{
Father(int x, int y) // parameterized constructor
{
int a = x;
int b = y;
System.out.println("Super Class Constructor a = "+a);
System.out.println("Super Class Constructor b = "+b);
}
Father(int z) // parameterized constructor
{
int d = z;
System.out.println("Super Class Constructor d = "+d);
}
}
class Son extends Father // Sub Class
{
Son() // default constructor
{
super(100);
super(10, 20); // Problem is here
int c = 200;
System.out.println("Sub Class Constructor c = "+c);
}
}
My question is can we use multiple super ( ) in subclass constructor as i want to initialize two super class Parameterized constructor. If it is not possible then how can i do this?
Your code is simply wrong. A constructor in Java has to always call exactly one super class constructor. There is no such thing as writing down super() twice in the same constructor.
In other words: the very first statement in a constructor is a call to a super-class constructor. If you don't put such a call there, the compiler will insert a call to super() behind the covers.
In that sense: when you are a beginner, and the compiler gives you an error message; the thing to do: turn to a good book or online resource.
My polemic answer is you don’t want to do that (feel free to challenge me). You want to design you superclass (Father) in such a way that it only takes one super constructor call to construct and initialize it so that it is ready for use.
In your example you haven’t got any fields in Father, so any of your constructors should be good enough for that. if you’re happy with the constructors you have but still want the output from both, there are a couple of options. First, you may add a three-arg constructor Father(int x, int y, int z) as Nghia Do suggested in a comment. You don’t need to delete the other two constructors if you prefer to have all three. Second, you may put in a method call instead of the second super call, and write a method in Father to print the message and do what other work you require. For the sake of code reuse, you ought to have the two-arg constructor call the same method rather than having the code duplicated.
Think what would happen if you had a class with two constructors and you needed to call both — if that was allowed. This would be a tricky bug waiting to happen. There would always be a risk that someone forgot to call both. You’d end up with some half-constructed object, and no one would know when something would go wrong when you used it.And when that happened, it would be far from obvious that it was due to the forgotten second constructor call. As I said, you don’t want that. The rule that Java always calls exactly one super constructor is a good one.

How to implement multiple subclasses with the same methods that use encapsulation?

I want to create a simple game in Java.
I'm struggling to understand how to use inheritance to accomplish how to implement subclasses that use encapsulation without needing to write out the same methods in the subclasses.
Ideally I'd like to make one base class "character" with a bunch of methods that use encapsulation, so that I can just declare different values for the private members of the subclasses. So something like,
public class Character {
private int hitPoints;
public int getHitPoints(){return hitPoints;}
}
And then just declare different values for the variables.
public class subCharacter extends Character {
private int hitPoints=100;
//getHitPoints() already inherited and should return 100
}
But to properly get the hit points of the subclass. I have to declare the same method in the subclass to actually get the method to work.
So isn't encapsulation incompatible with inheritance? Is there something basic here I'm misunderstanding or completely overlooking?
You should make the variable hitPoints protected in you Character class, and set it to 100 in the constructor of the subCharacter class. There is no need for the declaration of the getHitPoints method in the subclass. The code would look like this:
public class Character {
protected int hitPoints;
public int getHitPoints(){return hitPoints;}
}
public class subCharacter extends Character {
public subCharacter () {
hitPoints = 100;
}
}
Example of a subCharacter object:
subCharacter sub = new subCharacter();
System.out.println(sub.getHitPoints()); // prints 100
The reason this doesn't work like you think it should is because the subclass's hitpoints field is different from the superclass's hitpoints field. So while the superclass method is defined, it's trying to refer to a variable that you never actually initialized because it's not the same variable named hitpoints.
As others have already said, you should use the protected access modifier instead of the private access modifier on fields you want to have inherited to a subclass.
Then again, you probably don't actually need the SubCharacter class to begin with, if this is what you're actually writing for. You just need to have a constructor that takes a variable argument for hitpoints, or any other field in Character that needs to take different values.
//I'm not going to reproduce everything.
Character(int hp, String nm, boolean someBooleanThatIJustMadeUpToGetTheConceptAcross){
hitpoints = hp;
name = nm;
randomBoolean = someBooleanThatIJustMadeUpToGetTheConceptAcross;
}
This is not to say, however, that you don't need a superclass/subclass if, say, you're using this Character class for both enemies and player characters, for instance.
For an example of when you'd use inheritance...
public class Circle{
protected int radius;
Circle(){//It's always a good idea to have default constructors, by the way.
radius = 1;
}
Circle(int rad){
radius = rad;
}
}
public class Wheel extends Circle{
protected int numspokes;
Wheel(){
super(); //Calls the constructor for Circle, instead of reimplementing the wheel. badpuns++;.
numspokes = 0;
}
Wheel(int rad, int spokes){
super(rad); //This passes the radius up to the Circle this Wheel also is, so that any calls to this Wheel AS IF IT WAS a Circle, like an array or ArrayList of Circles, will function, which is the point of inheritance.
numspokes = spokes;
}
}

"Constructor call must be the first statement in a constructor" getting error in Java code?

I am getting two errors in this code
Constructor call must be the first statement in a constructor.
Implicit super constructor Parent() is undefined. Must explicitly invoke another constructor.
So please help me to resolve these issues.
class Parent
{
public Parent(int x, int y,int z)
{
System.out.println("Created Parent");
}
}
public class Child extends Parent
{
Child(int x)// error 2
{
}
Child(int x, int y)// error 2
{
}
Child(int x, int y, int z)
{
this(x);
super(x,y,z);// error 2
System.out.println("Creating child");
this(x,y);// error 1
}
public static void main(String [] args)
{
Child c=new Child(1,2,3);
}
}
There are four things you need to understand:
If you don't specify any explicit constructor call, the compiler inserts a call to super() for you.
There must be exactly one constructor call for any constructor- either explicit or the implicit super() call. (You've got three in your Child(int, int, int) constructor.
An explicit constructor call must be the very first statement in the constructor body.
You can only call a constructor which actually exists - so a call to super() from Child is looking for a parameterless constructor in Parent, which doesn't exist.
One frequent pattern is to have a "master" constructor which other constructors in the same class chain to, and then that one chains to the superclass. For example:
Child(int x)
{
this(x, 0); // Chains to the Child(int, int) constructor, defaulting y to 0
}
Child(int x, int y)
{
// Chains to the Child(int, int, int) constructor, defaulting z to 0
this(x, y, 0);
}
Child(int x, int y, int z)
{
super(x, y, z);
System.out.println("Creating child");
}
The first thing a constructor has to do is to invoke the parent class constructor.
The implicit default is super() (without any arguments), but that does not work in your case, because the parent class Parent does not have a no-arguments constructor, it only has one with three int arguments, so you need to invoke that one.
And you need to do that in the first line of the constructor.
Instead of calling the super constructor, you can also call another constructor (another this()) on the same class. The super constructor is assumed to be called by that other constructor (otherwise it would not compile).
But you have to call this() also in the first line of the constructor.
And after you have called this() or super(), you cannot call it a second time.
Child(int x)// error 2
{
}
Does not compile, because there is no super() to match the implicit call.
Child(int x, int y)// error 2
{
}
Same problem.
Child(int x, int y, int z)
{
this(x);
super(x,y,z);// error 2
System.out.println("Creating child");
this(x,y);// error 1
}
You cannot call super() or this() except on the very first line.
Answer is in the question. You have to call parent class constructor before any other statement in child class constructor.
public class Child extends Parent
{
Child(int x)// error 2
{
super(0,0,0);
}
Child(int x, int y)// error 2
{
super(x,y,0);
}
Child(int x, int y, int z)
{
super(x,y,z);
System.out.println("Creating child");
}
call to base constructor is not mandatory if base has a default constructor, this is not the case in your code.
The theory behind this is, in any inheritance hierarchy, when you instantiate any derived object, first the top most base will be initialized, then next of it and so on upto the actual derivation point.
When you create a new instance of Child class first thing to do is to call super(x,y,z), otherwise it cannot works. In fact a Child "is a" Parent, so to have an instance of Child you must be able to instantiate superclass. So Child(int x){ super(x,0,0);} is a possible constructor for Child class, but Child(int x){} isn't because Parent class does not have the default constructor. Remember that when you explicitly add a constructor to your class the default one is no more available. Finally, the constructor you wrote: Child(int x, int y, int z){this(x); super(x,y,z); this(x,y);} cannot works, because in a constructor you call three different constructors, but how many instances would you like to have? You can create just one instance per contructor.
When you instantiate a child object, the order of calling constructor is
Parent ---> followed by Child.
So The first line in your constructor has to be a call to the parent constructor. ( If you don't provide yourself, the compiler will insert one for you.) OR a call to own overloaded constructor (which will call super as explained above).
Your error 1 is caused because you have called the constructor only after certain executable statement are executed.
For error 2...
First thing you must know is that , a compiler will provide a default no-arg constructor for every class IF YOU DON'T PROVIDE ANY TYPE OF CONSTRUCTOR AT ALL.
But the moment , you provide a constructor , compiler no longer gives you a default constructor. you need to write one by yourself.
Second thing, by default , if you don't have a super() in your child class, the compiler will put by default a no-arg call to super().
This is where your problem lies.
You have given a parametrized constructor for your parent , and so compiler didn't provide with a no-arg default constructor. And now when in your child class you dont put your own super(xy,z) call, it will put a default no-arg super() call. BUT THE PARENT DOENST HAVE A NO AGR CONSTRUCTOR....hence the error.
You can do 2 things to solve this, either write a
Parent() {}
constructor
or put an explicit call to super -->
super (0,0,0)
in each child constructor

Java - subclass validation design pattern

I am having a base class C with fields X, Y and Z.
C1 extends C and is having an extra field, T.
In the C1 constructor, I do call the super (C) constructor with some hard coded values for the fields X, Y and Z. Then I set T.
Are there any patterns to automatically validate all the fields of C1 by doing something in the C constructor ? So I am trying to push the automatic validation to the base class.
Please note that calling the super constructor should be done before any statement in the C1 constructor. I started with some abstract validate() method, but I am not I am on the right track.
Thanks.
As a matter of principle, C should not know about C1's properties, because C1 is a specialization of C. However, what you can do is make an abstract validate() method in C, that must be implemented by C1. Then, in C's constructor, you can call the abstract method. Since, C1 will have to implement the validate(), it can then add it's property/field validation there.
Although it is against all OO principles, you could take advantage of Java's reflection property. Via reflection you can find out which methods and fields a class has. So you could pass the subclass object to the base class and the base class could check for all fields and validate them. If you do this at the end of the subclass constructor, you could let the validation method return a value to see if the values are valid or not.
I want to state that I don't think it's the right way to go but it should work
I would say that the super class should validate itself. An object needs to enforce its own contract. Any validation of C's values should be done in its own constructor. Likewise, the subclass should validate itself.
public class A {
private int x;
public A(int x) {
if (x < 0) throw new IllegalArgumentException("x cannot be negative");
this.x = x;
}
}
public class B extends A {
private String y;
public B(int x, String y) {
super(x);
if (y == null) throw new IllegalArgumentException("y cannot be null");
this.y = y;
}
}
class C{
Object x, y, z;
public C(Object x, Object y, Object z){
this.x = x;
this.y = y;
this.z = z;
}
public boolean validate(){ /**do stuff**/}
}
class D{
public D(/**args**/){
super(/**args**/);
if(validate()){
/**do stuff**//
}
}
}

Adding parameterless constructor to non-serializable, extendable class

What is special about addid a parameterless constructor to a non serializable, extendable class.
In Effective java , the author talks about this topic.
Naively adding a parameterless constructor and a
separate initialization method to a class whose remaining constructors establish its
invariants would complicate the state space, increasing the likelihood of error.
The following code is copied from Effective Java 2nd Edition[Page 292-293]
public class AbstractFoo {
private int x, y; // Our state
// This enum and field are used to track initialization
private enum State {
NEW, INITIALIZING, INITIALIZED
};
private final AtomicReference<State> init = new AtomicReference<State>(
State.NEW);
public AbstractFoo(int x, int y) {
initialize(x, y);
}
// This constructor and the following method allow
// subclass's readObject method to initialize our state.
protected AbstractFoo() {
}
protected final void initialize(int x, int y) {
if (!init.compareAndSet(State.NEW, State.INITIALIZING))
throw new IllegalStateException("Already initialized");
this.x = x;
this.y = y;
// ... // Do anything else the original constructor did
init.set(State.INITIALIZED);
}
// These methods provide access to internal state so it can
// be manually serialized by subclass's writeObject method.
protected final int getX() {
checkInit();
return x;
}
protected final int getY() {
checkInit();
return y;
}
// Must call from all public and protected instance methods
private void checkInit() {
if (init.get() != State.INITIALIZED)
throw new IllegalStateException("Uninitialized");
}
// ... // Remainder omitted
}
All public and protected instance methods in AbstractFoo must invoke
checkInit before doing anything else. This ensures that method invocations fail
quickly and cleanly if a poorly written subclass fails to initialize an instance. Note
that the initialized field is an atomic reference (java.util.concurrent.
atomic.AtomicReference). This is necessary to ensure object integrity in
the face of a determined adversary. In the absence of this precaution, if one thread
were to invoke initialize on an instance while a second thread attempted to use
it, the second thread might see the instance in an inconsistent state.
Why are we doing this? I did not fully understand this. Can anyone explain ?
I was having the same issue when reading the book. I was bit confused in that exact place. With bit of research I found out this.
http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
Read this. According to that
"During deserialization, the fields of non-serializable classes will be initialized using the public or protected no-arg constructor of the class. A no-arg constructor must be accessible to the subclass that is serializable. The fields of serializable subclasses will be restored from the stream"
I think this answers your question.
Hope this would be helpfull.
If there any thing wrong in this comment please feel free to correct it.
Separate initialization method is very useful when you have multi-threading issue. You can see good article : http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html

Categories

Resources