I want a bunch of subclasses to call a super method after finishing the constructor like this:
public abstract class Superclass {
...
public Superclass(...) {
... // do stuff before initializing subclass
}
protected void dispatch() { //method to be called directly after creating an object
doStuff();
...
}
public abstract void doStuff();
}
public class Subclass extends Superclass {
...
public Subclass(...) {
super(...); //has to be the first line
... //assign variables etc.
dispatch(); //has to be called after variables are assigned etc.
}
public void doStuff() {
//do stuff with assigned variables etc.
}
}
The dispatch() function contains a set of things to do with the object after it has been created, which has to apply to all subclasses. I can't move this function into the super constructor, since it calls methods from the subclasses which require already assigned variables. But since super() requires to be the first line of the sub constructor though, I can't set any variables until after the super constructor was called.
It would work as it is now, but I find it a bad concept to call dispatch() at the end of every subclasses' constructor. Is there a more elegant way to solve this? Or should I even completely rethink my concept?
Your request violates several Java best practices, e.g.:
Do not do complex configuration in a constructor, only fill private (final) member variables and do only very basic consistency checks (if any at all).
Do not call non private or non final methods from the constructor, not even indirectly.
So I would strongly suggest to think over the design of your classes. Chances are, that your classes are too big and have too many responsibilitis.
It would work as it is now, but I find it a bad concept to call
dispatch() at the end of every subclasses' constructor. Is there a
more elegant way to solve this? Or should I even completely rethink my
concept?
As underlined by Timothy Truckle, your constructor logic is too complex.
You can make things much simpler and reaching your goal by using the template method to initialize the subclass instance.
Note that you already used this pattern with doStuff().
The subclass constructor is indeed your issue here : you want to reduce the mandatory boiler plates required in each subclasss and also make their readability and maintenance better.
So introduce a new template method in the superclass and invoke it from the constructor of the super class.
This method will do the same thing as a constructor but could so be invoked in a more flexible way.
dispatch() that is an artificial method, introduced only for the trick is not required either.
The whole logic could be orchestrated from the super class constructor.
The super class could look like :
public abstract class Superclass {
...
public Superclass(...) {
... // do stuff before initializing subclass
init();
doStuff();
}
public abstract void init();
public abstract void doStuff();
}
And in the subclass, replace :
public Subclass(...) {
super(...); //has to be the first line
... //assign variables etc.
dispatch(); //has to be called after variables are assigned etc.
}
by :
public Subclass(...) {
super(...); // let the super constructor to orchestrate the init logic
}
public void init(){
// move the constructor logic here
}
The result is much simpler because this design gathers responsibilities related to the initialization "algorithm" of the subclass in a single place : the super class constructor.
About your comment :
This indeed looks way more elegant than what I did. Thank you! EDIT:
Just noticed, this does not work with subclasses having different
constructor parameters. Any idea how to solve this?
With such a requirement, to make things simple and clear, you have to make things in two steps :
instantiate the object
invoke on the reference the init() method.
It could look like :
SuperClass o = new Subclass(argFoo, argBar);
o.init();
The problem with this way is that you are not sure that the init() method was invoked. You could add a flag that you check at each time a method is invoked on the object. But it is really cumbersome and error-prone. Avoid that.
To improve that, I would probably use the wrapper pattern.
You could also use an interceptor/aspect. But it is not a good use case : the init processing is not transversal and is really related to the object behavior. It makes more sense to keep it visible.
With a wrapper, it could look like :
SuperClass o = new MyWrapper(new Subclass(argFoo, argBar));
Where The MyWrapper is a subclass of SuperClass and wraps an instance of SuperClass object :
public class MyWrapper implements SuperClass{
private SuperClass wrapped;
public MyWrapper (SuperClass wrapped){
this.wrapped = wrapped;
this.wrapped.init();
}
// then delegate each superclass method to the wrapped object
public void doStuff(){
this.wrapped.doStuff();
}
// and so for...
}
Lorelorelore is correct, if you do need any subclass instantiation to be complete when the method is called. Otherwise, you can do what you have. I would suggest putting adequate comments if others will need to use the code.
You can abstract the use of your SuperClass by providing a static method which will execute the code you want, but also checks that it has been setup correctly:
public abstract class SuperClass{
private boolean instantiated;
public SuperClass(...){
...
}
public abstract void doStuff();
private void dispatch(){
if(!instantiated){
instantiated = true;
doStuff();
}
}
public static void executeActionOnSuperClass(SuperClass s){
s.dispatch(); // call instantiation if not already done
s.executeAnAction();
}
}
And the subclass:
public class SubClass extends SuperClass{
public SubClass(...){
super(...);
}
public void doStuff(){
...
}
}
Which then can be executed like this:
SuperClass.executeAnActionOnSuperClass(new SubClass(...));
Though this is mostly an anti pattern and should be used sparely.
Related
let me first explain what i want to say actually
Suppose a class Sub inheriting the class Super.
now we can excess all no private members of class Super within class Sub. now Suppose the case
class Super{
private int id;
public int getId()
{
return id;
}
}
class Sub extends Super {
public static void main(String args[]){
Sub sub = new Sub();
System.out.println(sub.getId());
}
}
I know that creating Sub class object will call Super class constructor too.
But the job of constructor is to initialize the fields only -- not to allocate the memory to the object.
Moreover in case of abstract class where the initialization is not allowed we can still use the instance variable of abstract class.
The memory to instance variable will be assigned at time of instance creation only.
Than how can we use the instance fields without even creating the instance.
Doesn't it violets the oops concept..??
Please help over this. And thanks in advance.
I think you're confused about what happens when you use the extends keyword. What that keyword means is that a Sub is a more-specific kind of Super. By the Liskov Substitution Principle, all of the properties of Super must hold for Sub as well. That means that all of Super's private members (methods and properties) are present in an instance of Sub. It's just that for organizational reasons, the developer of Super decided that they didn't want any derived classes messing around with it directly.
Now, how does this relate to memory allocation? In the case of Java, you are correct that the constructor does not allocate memory. It just initializes the fields. The memory allocation is handled by the runtime, and it allocates enough for the whole picture. Remember, a Sub is a Super and then some. So it allocates enough memory to hold everything from the entire inheritance chain all the way back up through java.lang.Object.
abstract classes can, in fact be initialized, or even force their derived classes to initialize their members. For example:
public abstract class Super {
private int id;
public Super(int id) {
this.id = id;
}
public int getId() { return this.id; }
}
public class Sub extends Super {
public Sub() {
super(5); // failure to call this constructor is a compiler error
}
}
Now, because Sub can't see Super's private id field, it's free to declare a new one of its own. This does not override Super's field. Any of Super's methods that use that field will still use the one from Super. This could be a little confusing, so the best advice is don't think of it that way. Generally, you'll want to override methods not fields.
I totally agree with the answer of Ian. Totally. Regarding the title of your question,
Does inheritance violates the basic law of oops..?
the answer is it depends. There is a kind of inheritance that violates encapsulation principle: implementation inheritance.
You're using implementation inheritance every time you inherit (through extends primitive) from a class that is not marked as abstract. In that case, to know how to implement your subclass, you need to know the implementation (a.k.a. the code) of methods of the base class. When you override a method, you have to know exactly which is the behavior of that method in the base class. This kind of code reuse is often referred to as white-box reuse.
Quoting the GoF's book, Design Pattern:
Parent classes often define at least part of their subclasses' physical representation. Because inheritance exposes a subclass to details of its parent's implementation, it's often said that "inheritance breaks encapsulation".
So, to reduce implementation dependencies, you have to follow one of the principles of reusable object-oriented design, which is:
Program to an interface, not an implementation
inheritance only concern about what and how is accomplished, not what is promised. If you violate the promises of the base class, what will happen? is there any guarantee that makes you sure it's compatible? -even your compiler will not understand this mistake and you will face a bug in your codes. Such as:
class DoubleEndedQueue {
void insertFront(Node node){
// ...
// insert node infornt of queue
}
void insertEnd(Node node){
// ...
// insert a node at the end of queue
}
void deleteFront(Node node){
// ...
// delete the node infront of queue
}
void deleteEnd(Node node){
// ...
// delete the node at the end of queue
}
}
class Stack extends DoubleEndedQueue {
// ...
}
if the class wants to use inheritance with aim of code reuse, It may inherit a behavior that violates its principal, such as insertFront. Let's also see another code example:
public class DataHashSet extends HashSet {
private int addCount = 0;
public function DataHashSet(Collection collection) {
super(collection);
}
public function DataHashSet(int initCapacity, float loadFactor) {
super(initCapacity, loadFactor);
}
public boolean function add(Object object) {
addCount++;
return super.add(object);
}
public boolean function addAll(Collection collection) {
addCount += collection.size();
return super.addAll(collection);
}
public int function getAddCount(Object object) {
return addCount;
}
}
I just reimplement HashSet with DataHashSet class in order to keep track of inserts. In fact, DataHashSet inherit and is a subtype of HashSet. we can instead of HashSet just pass DataHashSet(in java is possible). Also, I do override some of the methods of the base class. Is this legitimate from Liskov substitution principle? As I do not make any changes in the behavior of base class just add a track to insert actions, It seems perfectly legitimate. But, I will argue this is obviously a risky inheritance and a buggy code. First, we should see what exactly add method do. add one unit to related property and call parent class method. There is a problem with that called yo-yo. Look at addAll method, first, it adds collection size to related property then call addAll in the parent, but what exactly parent addAll do? It will call add method several times(loop over the collection), which add will be called? the add in the current class, so, the size of count will be added twice. once when you call addAll and second when parent class will call add method in the child class, that's why we call it yo-yo problem. And another example, imagine:
class A {
void foo(){
...
this.bar();
...
}
void bar(){
...
}
}
class B extends A {
//override bar
void bar(){
...
}
}
class C {
void bazz(){
B b = new B();
// which bar would be called?
B.foo();
}
}
As you see in bazz method which bar will be called? the second one the bar in class B will be called. but, what is the problem here? the problem is foo method in class A will not know anything about the override of bar method in class B, Then your invariants may be violated. because foo may expect the only behavior of bar method that is in own class, not something is overridden. This problem is called fragile base-class problem.
One of my classes inherits from a class in a framework I use. The superclass calls a method in its constructor which I overwrite in my own class.
The method uses a field I want to initialize before it is called by the super constructor to avoid a NullPointerException.
Is there any way to do this?
Here is a synthetic test scenario, I want c in Child to not be null when call is called.
public class Test {
public static class Parent {
public Parent() {
super();
call();
}
// only called from parent constructor
public void call() {
System.out.println("Parent");
}
}
public static class Child extends Parent {
private Child c = this;
public Child() {
super();
}
// only called from parent constructor
public void call() {
System.out.println("Child, c is " + (c == null ? "null" : "this"));
}
}
public static void main(String[] args) {
new Child();
}
}
Prior to Java 7, that was possible. I could get by with stunts like this:
public static class Child extends Parent {
private Child c;
private Child(Object unused) {
super();
}
public Child() {
this(c = this);
}
// only called from parent constructor
public void call() {
System.out.println("Child, c is " + (c == null ? "null" : "this"));
}
}
Now, that won't work anymore. I appreciate the additional safety, but the call from super destroys any safety gained by it and reduces the flexibility.
I'd like a way to circumvent this restriction.
As an alternative, I'd like to know what's gained by an restriction that spares the super constructor case.
A static initializer will be called before the super class constructor. However, you won't be able to set any non-static fields, so it most likely won't help.
http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
A non-static initialization block also doesn't help as it is called after the super class constructor completes.
Another approach may be to do nothing when called from the super-constructor and make the call again the child constructor, e.g:
public Child() {
super();
call();
}
public void call() {
if (c==null) {
return;
}
System.out.println("do something with c now");
}
This won't work if more stuff happens in the super constructor that is dependent on this method though.
I have to agree with EJP that this is all a bad idea; it would be much better to find a completely different solution that doesn't involve torturing constructors.
This is an answer to the "I'd like to know what's gained by an restriction that spares the super constructor case." part of the question.
In the course of construction, there are three states the fields declared in a class X might be in: All default values, all fully initialized to consistent working values, and anything else.
The objective seems to be that code in classes other than X only sees one of the first two states. When non-static initializer or constructor code for any of X's superclasses is running, X's fields are all in the default state. When non-static initializer or constructor code for any subclass of X is running, all X's fields have been initialized to a fully consistent, usable state.
Only X initializer and constructor code should have to deal with X fields in an inconsistent state, some initialized, some default, and some partially initialized.
This can certainly be circumvented by calling X methods from an X superclass initializer or constructor, but that is commonly regarded as an anti-pattern. The problem is running X code that is not called locally from an initializer or constructor in a partially constructed X. If that code changes a field, the change may be overwritten when the X initializers and constructor body run.
Note that your class Child is translated into the following equivalent by the Java compiler:
public static class Child extends Parent {
private Child c;
public Child() {
super();
c = this;
}
// Remaining implementation
}
This is the same for Java 6 and 7, the generated byte code for the constructor is even the same when compiling with any of both versions. The local field is always instantiated after calling the super constructor. What compiler did you use to make your "work-around" work?
This restriction is quite elementary. This way, you can rely on that super constructors are applied first. Imagine, your sub constructor was using a final field declared in this class. You could not guarantee that this field was initialized if you would not guarantee this constructor execution order. This restriction makes Java more reliable.
This should never have worked in the first place.
Note that at the bytecode level, this actually is allowed. In bytecode, you can set fields declared in the current class before calling a superclass constructor. However, Java provides no way to use this behavior. It is only used secretly by the Java compiler to initialize the synthetic fields added to support inner classes.
I'm trying to get the hang of inheritance in Java and have learnt that when overriding methods (and hiding fields) in sub classes, they can still be accessed from the super class by using the 'super' keyword.
What I want to know is, should the 'super' keyword be used for non-overridden methods?
Is there any difference (for non-overridden methods / non-hidden fields)?
I've put together an example below.
public class Vehicle {
private int tyreCost;
public Vehicle(int tyreCost) {
this.tyreCost = tyreCost;
}
public int getTyreCost() {
return tyreCost;
}
}
and
public class Car extends Vehicle {
private int wheelCount;
public Vehicle(int tyreCost, int wheelCount) {
super(tyreCost);
this.wheelCount = wheelCount;
}
public int getTotalTyreReplacementCost() {
return getTyreCost() * wheelCount;
}
}
Specifically, given that getTyreCost() hasn't been overridden, should getTotalTyreReplacementCost() use getTyreCost(), or super.getTyreCost() ?
I'm wondering whether super should be used in all instances where fields or methods of the superclass are accessed (to show in the code that you are accessing the superclass), or only in the overridden/hidden ones (so they stand out).
Don't use the super keyword to refer to other methods which aren't overridden. It makes it confusing for other developers trying to extend your classes.
Let's look at some code which does use the super keyword in this way. Here we have 2 classes: Dog and CleverDog:
/* file Dog.java */
public static class Dog extends Animal {
private String name;
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
/* file CleverDog.java */
public class CleverDog extends Dog {
public CleverDog(String name) {
super(name);
}
public void rollover() {
System.out.println(super.getName()+" rolls over!");
}
public void speak() {
System.out.println(super.getName() + " speaks!");
}
}
Now, imagine you are a new developer on the project, and you need some specific behavior for a clever dog who is on TV: that dog has to do all its tricks, but should go by its fictitious TV name. To accomplish this, you override the getName(...) method...
/* file DogOnTv.java */
public class DogOnTv extends CleverDog {
String fictionalName;
public DogOnTv(String realName, String fictionalName) {
super(realName);
fictionalName = fictionalName;
}
public String getName() {
return fictionalName;
}
}
... and fall into a trap set by the original developer and their unusual use of the super keyword!
The code above isn't going to work - because in the original CleverDog implementation, getName() is invoked using the super keyword. That means it always invokes Dog.getName() - irrelevant of any overriding. Consequently, when you use your new DogOnTv type...
System.out.println("Showcasing the Clever Dog!");
CleverDog showDog = new CleverDog("TugBoat");
showDog.rollover();
showDog.speak();
System.out.println("And now the Dog on TV!");
DogOnTv dogOnTv = new DogOnTv("Pal", "Lassie");
dogOnTv.rollover();
... you get the wrong output:
Showcasing the Clever Dog!
Tugboat rolls over!
Tugboat speaks!
And now the Dog on TV!
Pal rolls over!
Pal speaks!
This is not the usual expected behavior when you override a method, so you should avoid creating this kind of confusion using the super keyword where it doesn't belong.
If, however, this is actually the behavior you want, use the final keyword instead - to clearly indicate that the method can't be overridden:
/* file CleverDog.java */
public class CleverDog extends Dog {
public CleverDog(String name) {
super(name);
}
public final String getName() { // final so it can't be overridden
return super.getName();
}
public void rollover() {
System.out.println(this.getName()+" rolls over!"); // no `super` keyword
}
public void speak() {
System.out.println(this.getName() + " speaks!"); // no `super` keyword
}
}
You are doing the right way by not using the super keyword for accessing getTyreCost.
But you should set your members private and only use the getter method.
Using super keyword should be reserved for constructors and overridden methods which need to explicitly call the parent method.
This would be dependent on how you plan to use the code. If you specify super.getTyreCost() and then later override that method. You will still be calling the method on the superclass, not the overridden version.
In my opinion, calling super is likely to lead to more confusion later on, so is probably best specified only if you have an explicit need to do so. However, for the case you have presented here - there will be no difference in behavior.
It depends on your needs and your desires. Using super forces the compile/application to ignore any potential methods in your current class. If you want to communicate that you only want to use the parent's method, then using super is appropriate. It will also prevent future modifications to your class to accidentally override the parent method thereby ruining your expected logic.
However, these cases are fairly rare. Using super everywhere within your class will lead to very confusing & cluttered code. In most general cases, just calling the method within your own class and allowing the compiler/jvm to determine which method (super or local) needs to be called is more appropriate. It also allows you to override/modify/manipulate the super's returning values cleanly.
If you use super, you are explicitly telling to use super class method (irrespective of sub class has overridden method or not), otherwise first jvm checks for the method in subclass (overridden method if any), if not available uses super class method.
overriding means redefining a method from the superclass inside a subclass with identical method signature. In your case, the getTyreCost() method has not been overridden, you have not redefined the method in your subclass, so no need to use super.getTyreCost(), only getTyreCost() will do(just like super.getTyreCost() will do the same way). super keyword is used when a method has been overridden, and you want a method call from within your subclass to be implemented in the superclass.
Technically, the one that's invoked in this case is the inherited version, for which the implementation is actually provided by the parent class.
There can be scenarios where you must use the super keyword. e.g. if Car had overridden that method, to provide a different implementation of itself, but you needed to invoke the implementation provided by the parent class then you would have use the super keyword. In that case, you could not afford to omit the super keyword because if you did then you would be invoking the implementation provided by the child class itself.
It is advised that further changes to the inherited class will not necessitate addition of the super qualifier and also prevent errors if missed.
why should we widen the accessibility of overridden methods ? If the super class has a protected method and subclass has same method with public. Why should happen?
It's a different method! Subclasses don't inherit private methods! So you're not "overriding" at all. You are simply DEFINING a method with the same name as the private method in the superclass.
class A
{
private void myMethod() { }
}
class B extends A
{
public void myMethod() { } // a completely different method. Has nothing to do with the above method. It is not an override.
}
Because in an object hierarchy, JVM will always run the Overriden method. If your overriden method is not accessible, then it is useless.
public class A{
void A(){}
}
public class B extends A{
private void A(){} //this makes no sence and its impossible
PSV main(String ..){
A a = new B();
a.A(); //error as JVM cannot call overriden method which is private.
}
}
Methods declared as private or static can not be overridden!
Annotation #Override indicates that a method declaration is intended to override a method declaration in a superclass. If a method is annotated with this annotation type but does not override a superclass method, compilers are required to generate an error message.
Use it every time you override a method for two benefits. This way, if you make a common mistake of misspelling a method name or not correctly matching the parameters, you will be warned that you method does not actually override as you think it does. Secondly, it makes your code easier to understand because it is more obvious when methods are overwritten.
And in Java 1.6 you can use it to mark when a method implements an interface for the same benefits.
i have an abstract class BaseClass with a public insert() method:
public abstract class BaseClass {
public void insert(Object object) {
// Do something
}
}
which is extended by many other classes. For some of those classes, however, the insert() method must have additional parameters, so that they instead of overriding it I overload the method of the base class with the parameters required, for example:
public class SampleClass extends BaseClass {
public void insert(Object object, Long param){
// Do Something
}
}
Now, if i instantiate the SampleClass class, i have two insert() methods:
SampleClass sampleClass = new SampleClass();
sampleClass.insert(Object object);
sampleClass.insert(Object object, Long param);
what i'd like to do is to hide the insert() method defined in the base class, so that just the overload would be visible:
SampleClass sampleClass = new SampleClass();
sampleClass.insert(Object object, Long param);
Could this be done in OOP?
There is no way of hiding the method. You can do this:
#Override
public void insert(Object ob) {
throw new UnsupportedOperationException("not supported");
}
but that's it.
The base class creates a contract. All subclasses are bound by that contract. Think about it this way:
BaseObject b = new SomeObjectWithoutInsert();
b.insert(...);
How is that code meant to know that it doesn't have an insert(Object) method? It can't.
Your problem sounds like a design problem. Either the classes in question shouldn't be inheriting from the base class in question or that base class shouldn't have that method. Perhaps you can take insert() out of that class, move it to a subclass and have classes that need insert(Object) extend it and those that need insert(Object, Object) extend a different subclass of the base object.
I don't believe there's a clean way to completely hide an inherited method in Java.
In cases like this, if you absolutely can't support that method, I would probably mark that method as #Obsolete in the child class, and have it throw a NotImplementedException (or whatever the equivalent exception is in Java), to discourage people from using it.
In the end, if you inherit a method that does not make sense for your child class, it could be that you really shouldn't inherit from that base class at all. It could also be that the base class is poorly designed or encompasses too much behavior, but it might be worth considering your class hierarchy. Another route to look at might be composition, where your class has a private instance of what used to be the base class, and you can choose which methods to expose by wrapping them in your own methods. (Edit: if the base class is abstract, composition might not be an option...)
As Cletus points out, this is really a design problem, in that you are trying to create a child class that does not obey the contract of its parent class.
There are rare circumstances where working around this by e.g. throwing an exception might be desirable (or at least an acceptable compromise -- for example, the Java Collections Framework) but in general it's a sign of poor design.
You may wish to read up on the Liskov substitution principle: the idea that (as Wikipedia puts it) "if S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program". By overriding a method to throw an exception, or hiding it any other way, you're violating this principle.
If the contract of the base class' method was "inserts the current object, or throws an exception" (see e.g. the JavaDoc for Collection.add()) then you could argue you're not violating LSP, but if that is unexpected by most callers you may want to rethink your design on these grounds.
This sounds like a badly designed hierarchy -
If no default exists and the user shouldn't call the method at all you can mark the method as #Deprecated and throw an UnsupportedOperationException as other posters have noted. However - this is really only a runtime check. #Deprecated only throws a compiler warning and most IDEs mark it in some way, but there's no compile time prevention of this. It also really sucks because it's possible to get the child class as a parent class reference and call the method on it with no warning that it's "bad" at all. In the example below, there won't be any indication until runtime that anything's wrong.
Example:
// Abstract base builder class
public abstract class BaseClassBuilder {
public final doBuild() {
BaseClass base = getBase();
for (Object obj : getObjects() {
base.insert(obj);
}
}
protected abstract BaseClass getBase();
protected abstract Object[] getObjects();
}
// implementation using SampleClass
public class SampleClassBuilder extends BaseClassBuilder {
#Override
protected BaseClass getBase() {
return new SampleClass();
}
#Override
protected Object[] getObjects() {
Object[] obj = new Object[12];
// ...
return obj;
}
}
However, if a sensible default exists, you could mark the inherited method as final and provide the default value inside of it. This handles both the bad hierarchy, and it prevents the "unforseen circumstances" of the above example.
Example:
public abstract class BaseClass {
public void insert(Object object) {
// ...
}
}
public class SampleClass extends BaseClass {
public static final Long DEFAULT_PARAM = 0L;
public final void insert(Object object) {
this.insert(object, DEFAULT_PARAM);
}
public void insert(Object object, Long param) {
// ...
}
}