Let's consider two classes, SuperClass, and SubClass which extends it:
Class SuperClass{
int superDataMember;
}
Class SubClass extends SuperClass{
int subDataMember;
}
I need to have another CompositeClass class that may use super or sub composition depending on some criteria. My question is: Should I use
An instance of SuperClass inside CompositeClass
Thus, I can use either SuperClass instance or SubClass instance.
But how will methods accessing subDataMember behave if the accessed instance is of SuperClass?
Maybe an instanceOf check may work at the beginning of each method?
Class CompositeClass {
private SuperClass sc;
public getSuperDataMember () {// some code}
public getSubDataMember () {
if (this.sc instanceOf SubClass)
// some code
}
}
An instance of SubClass inside CompositeClass
Thus, I will lose the ability to access SuperClass instances!
Class CompositeClass {
private SubClass sc;
public getSuperDataMember () {// some code}
public getSubDataMember () {// some code
}
}
Implement two versions of CompositeClass, the first is SuperCompositeClass with an instance of SuperClass and the second SubCompositeClass that extends the first with an instance of SubClass!
Mind that a SubClass is also a SuperClass so you won't lose the ability to access the component as a SuperClass like you pointed out.
In addition there is a third option, using parametric polymorphism:
class CompositeClass<T extends SuperClass>
{
private T component;
...
}
So that you can adapt it to the specific situation. This will require you to override additional methods if not provided by the interface of SuperClass though.
It sounds to me from your problem like your two classes might be better as siblings implementing an abstract class's methods than as a parent child relationship. This allows you to easily use polymorphism, using instanceOf if need be. A parent child relationship is most purely used when the child needs to retain all information and functionality of the parent.
Related
Assume for some reason that I don't want to implicitly call super() which is done by default.
class Animal {
public Animal() {
System.out.println("Constructing an animal.");
}
}
class Dog extends Animal {
public Dog() {
System.out.println("Constructing a dog.");
}
public static void main(String[] a) {
new Dog();
}
}
Is there any way to "disable" the default behavior that super() is invoked when making a new Dog? Or would that be principally and conceptually wrong?
I mean there could be cases where you would want only the constructor of the subclass and not invoke the construction of the baseclass, and still inherit the baseclass.
If I understand you correctly you want to override the behavior of the Animal constructor or just not call it. If so you're conceptually wrong: you always need to call a super constructor, the only thing you could to with the calls is provide a non-default constructor, i.e. one with arguments and provide appropriate arguments to influence the behavior of that constructor (e.g. by either selecting a different constructor, passing some sort of strategy/function object etc.)
Another way might be to provide some init() method that the default constructor is calling and which you can override but there are a few problems with it, e.g.:
If the overridden method tries to access anything only visible to the subclass (e.g. additional fields) you could run into problems because those haven't been initialized yet.
That method can't initialize any final field.
s there any way to "disable" the default behavior that super() is
invoked when making a new Dog? Or would that be principally and
conceptually wrong?
It is conceptually wrong since any class which invokes its constructor has to invoke the constructor of its parent : super() or super() with any arguments if the super constructor has not it.
If the constructor of the super class does some specific processing and that is not desirable for all concrete classes, you should change rather the implementation of the super constructor and move the specific behavior in a method of the super class or in a method of concrete classes.
You can't bypass the construction of a parent class, and perhaps you shouldn't attempt to circumvent this rule.
But, if you must do this then you could build a no-op constructor in Animal (that you mark as protected so only derived classes can see it):
protected Animal(Noop foo)
{
/*do nothing explicit here*/
}
And call that one explicitly from your derived class using
super(new Noop())
Here I've invented a new class Noop (meaning "no operation") to enable the compiler to distinguish the constructor parameters.
Agreeing with all the answers here on invoking the constructor which cannot be avoided, providing one more workaround which ensures a block of code in constructor that gets executed only when it is directly invoked and not when any sub class constructors are invoked.
public class Animal{
public Animal() {
if(this.getClass() == Animal.class){
System.out.println("Animal");
}
}
}
public class Dog extends Animal{
public Dog() {
System.out.println("Dog");
}
}
That's one of the reasons inheritance is a pain and usually misused:
public interface Animal {
// define behaviour
}
public class Dog implements Animal {
// implement behaviour
}
Use interfaces and aggregation / decoration so you can avoid the struggle of bad design decisions in inheritance chains.
Hey i'm trying to call child class method(ChildClass extends SuperClass())
SuperClass s=new ChildClass();
s.childClassMethod();
It doesn't see the ChildClass method the only methods i can call are from SuperClass()
i know it's propably a stupid question but anyway cheers
That's right, you can't see it because s is type SuperClass which doesn't have this method - this would obviously break Polymorphism principle.
So you either have to change the code like ((ChildClass) s).childClassMethod(); or make s as ChildClass type.
Compiler doesn't know what instance this reference would be pointing to at runtime so it will only allow you to access super class's accessible methods at compile time
See
polymorphism
The parent does not know anything about any new methods the child possesses.
public class SuperClass {
// I have no method named "childClassMethod"...
}
public class ChildClass {
public void childClassMethod() {
// Do something.
}
}
SuperClass does not know about childClassMethod(). You would have to provide both classes with an interface or add that method to the parent and override it in the child.
Or, you could simply cast the object to the child class as others have suggested, but this can be unsafe.
((ChildClass) s).childClassMethod()
That is because the super class does not have that method.
If you want the super class to be able to call the method, you need to make it abstract and give it that method.
The subclass is a form of the super class, the super class is not a form of the sub class.
In Java, when I override a method the compiler flags off any attempt to narrow down the visibility as an error. For ex: I can't override a public method as protected, while I can override a protected method as public.
I am interested in knowing the design decision/thinking behind this rule.
A subclass should always satisfy the contract of the superclass. See Liskov Substitution principle.
The visibility of methods is part of this contract. So anything publicly visible in the superclass should be public in the subclass as well.
Consider a class B which inherits from A. A.m() is public. Now consider this code:
A obj = new B();
obj.m();
Should this call be allowed? Yes, it should, because obj is an object of type A! It is also an object of type B, but that is not necessarily known to the one using the object.
Every object of type A must adhere to the contract (interface) for A. B extends A and must therefore also adhere to that contract.
While over ridding or implementing the access level, we should go for same access level or wider to that access level.
private < (default) < protected < public
Public is wider most level.
In Interface all members are default public. So, While implementing or over ridding we have to go for only public.
Assume parent class and child class with overriding method with public access modifier.
class Parent{
public void m(){
// method implementation
}
}
class Child extends Parent{
#Override
public void m(){
//child implementation
}
}
assume there are some classes which are utilising this functionality like this
Parent p = new Child();
p.m(); // this access is fine, because JVM calls Overriding method at run time
Now if we change the access of overriding method to anything less than public
class Child extends Parent{
#Override
void m(){
//Child implementation
}
}
Now some of the classes which were able to use the functionality of method m() may not be able access the function.This is not a desired behaviour.
Hence the rule is Overriding method should not decrease the scope of overridden method.
Is it really necessary to implement all the methods to a subclass(inherited from a abstract class), if there is another subclass of that abstract class has already implemented those abstract methods?
abstract class A {
abstract void method();
abstract void anothermethod();
}
class B extends A {
void method() {}
void anothermethod() {}
}
class C extends A { // is this class definition is legal?
void sample() {}
}
Only if you mark C as an abstract class. Therefore passing on its implementation responsibilities to it's subclasses.
Another option would be to have C extend B, and therefore B would contain the implementation demanded of A by its subclasses.
No, it's not legal. You've got a concrete class (C is not declared abstract) extending an abstract class, but without providing implementations for its methods. It's not really clear why you think this should or could be legal - and you should consider whether this has wider ramifications for your understanding of inheritance in general than just this specific case.
C is entirely separate from B. They could have entirely different state - for example, B might implement method() using some state which is only present in an instance of B. It's important to understand that an instance of C is not an instance of B.
If you want it to inherit its behaviour, you should make C subclass B instead of A.
No. Class C will be abstract in this case, too.
What about class C extends B?
Thats absolutely illegal unless you make the class "C" abstract as IronBlossom suggested or implements all the abstract method of class "A"in class "C".
Is there any keyword or design pattern for doing this?
Please check the update
public abstract class Root
{
public abstract void foo();
}
public abstract class SubClass extends Root
{
public void foo()
{
// Do something
//---------------- Update -------------------//
// This method contains important code
// that is needed when I'm using a instance
// of SubClass and it is no instance of any
// other class extending SubClass
}
}
public class SubberClass extends SubClass
{
// Here is it not necessary to override foo()
// So is there a way to make this necessary?
// A way to obligate the developer make again the override
}
Thanks
If you are doing this, then you are probably abusing inheritance; inheritance, contrary to popular myth, is not intended for making custom hooks/handlers, but rather to enable alternative implementations.
If you want your user to provide some sort of function/hook/callback, then you should define an interface that provides just those methods that you need your user to define. Then you should require the user to pass in an instance of that interface to your object's constructor or passed into the function that needs it.
Aggregation, delegation, and composition are frequently better and safer design patterns than inheritance; forcing other users to inherit from your class, is incredibly risky, as it provides the user with many opportunities to violate the contract of your class or to invalidate the invariant of your base class.
If every class subclassing SubClass has to override foo() then why provide an implementation at all in SubClass? You can simply remove the method definition from SubClass and then all subclasses will be forced to provide an implementation.
If you really want to, you can re-declare foo as abstract.
public abstract class SubberClass extends SubClass
{
public abstract void foo();
}
Instead of overriding foo() in SubClass, create a new method fooImpl() and leave foo() abstract. This way, all classes must implement foo() but you can simply implement it by calling fooImpl() if that is already enough.
Yeah it is not necessary to override foo() in SubberClass.
You can't have it both ways. You can't provide a method with a default implementation AND require child classes override it. Instead of declaring the method as abstract in Root, you could define an interface (IFoo) with the method declared and then provide an abstract class that implements the interface. That would still require a concrete child class but would not require a method override.
Most of the time you see this type of pattern, an interface is used to define a set of methods and an abstract base class provides some default implementations for some but not all methods from the interface. This requires the concrete child class to provide code for the remaining methods and the option to override the default behaviors.
In any case, you can't provide a default behavior for a single method and require child classes to override that same method.