07-19-2016 4:06 PM
Hi,
I have been reading various posts on OOPS ABAP and below is the inference i have got so far.
We go for abstract classes when we have some common functions and some unique functions respective to implementing class.
Interfaces can also achieve what is mentioned above about abstract classes but we mainly go for it for polymorphism and when there is no need for common functions/global functions between implementing classes
My question is ?? what i told about abstract class can also be achieved using class-methods, class-data (for global functions) and normal class inheritance (for redefining unique functions), then why should we go for abstract classes.
Moreover, we have a disadvantage with abstract classes, that all the implementing classes must redefine all the abstract methods. We add a new abstract method to an abstract class, we need to define it in all implementing classes.
Then why are we not sticking with using class-method and normal inheritance and instead go for abstract classes?
Even interfaces have this disadvantage, but it is the only way for polymorphism.
Also, the global/common methods of an abstract class can be redefined where as class-methods cannot be, helping us achieve OO Pardigm better.
Could anyone please help me understand this, please forgive me if i am wrong anywhere.
07-19-2016 7:41 PM
Hello All,
Thank you so much, the below try out was what actually made me doubt why and when do we really need abstract class ( programming wise, not conceptual )
A scenario
abstract_class
method display importing info FINAL "common method
abstract method "get info" "method for redefinition
"if we add new abstract method we need to redefine in all classes - Issue
class1 inheriting from abstract_class
redefine method "get info" to "get name info"
class2 inheriting from abstract_class
redefine method "get info" to "get age info"
class_trigger
class-method call_all importing classimp type ref to abstract_class
call method classimp->get_info()
call method classimp->display()
endmethod
create objects class1, class2
class_trigger->call_all ( class1 ).
class_trigger->call_all ( class2 ).
Now, I can do the same using class-method and normal redefinition
Main_class
class-method display importing info "common method
method "get info" ""method for redefinition
class1 inheriting from main_class
redefine method "get info" to "get name info"
class2 inheriting from main_class
redefine method "get info" to "get age info"
class_trigger
class-method call_all importing classimp type ref to abstract_main
call method classimp->get_info()
call method classimp->display()
endmethod
create objects class1, class2
class_trigger->call_all ( class1 ).
class_trigger->call_all ( class2 ).
i think that's what i am trying to know, why go through the trouble of creating abstract classes methods and compel implementing classes to redefine them all.
@Frank kirck , could you please help me understand this scenario and why abstract is needed
07-19-2016 4:25 PM
Puhhh, where to start?
In the usual case you use abstract classes i.e. abstract methods only for these cases, where you really want to redefine it always in the sub classes. It's not needed to define all methods as abstract, you can implement methods also in an abstract class.
Of course you can also avoid a redefinition of an already implemented method by using FINAL.
Interfaces are good to hide implementations (open-close-principle) and to seperate concerns. They are also very good for dependency injections in well layered applications.
If you say, you can implement the functionalities also as static methods, then it sounds like you need in fact helper or utility classes. So you should not take inheritance as solution, but delegation.
07-19-2016 5:21 PM
Hello Armin,
Thank you.
"FINAL" is a great solution to prevent redefinition of abstract classes' common methods, but i still don't understand why were abstract classes formed when we could do it all using simple static methods and normal redefinition of a super classes' methods.
Can you explain more about "it sounds like you need in fact helper or utility classes. So you should not take inheritance as solution, but delegation"
07-19-2016 6:32 PM
Hi Madhu,
in short, because you often can not. Consider this example in my pseudo language:
class Primitive {
abstract draw(canvas);
}
class Line extends Primitive {
private x_1, y_1, x_2, x_2;
draw(canvas) {
canvas.drawLine(x_1, y_1, x_2, y_2);
}
}
class Rect extends Primitive {
private x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4;
draw(canvas) {
canvas.drawRect(x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4);
}
}
Now you can have drawing code that always draws the correct shape with the correct points. E.g:
primitives = [ new Line(), new Line(), new Rect() ];
for (primitive in primitives) { primitive.draw() };
This would not work that easily if you'd use static methods because you'd have to check from which class the static method has to be called, e.g.:
class Primitive {}
class Line extends Primitive {
private x_1, y_1, x_2, x_2;
static draw(line, canvas) {
canvasdrawLine(line.x_1, line.y_1, line.x_2, line.y_2);
}
}
class Rect extends Primitive {
private x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4;
static draw(rect, canvas) {
canvas.drawRect(rect.x_1, rect.y_1, rect.x_2, rect.y_2, rect.x_3, rect.y_3, rect.x_4, rect.y_4);
}
}
Your drawing code will now have to do sth. like this:
primitives = [ new Line(), new Line(), new Rect() ];
for (primitive in primitives) {
if (typeof(Primitive) == Line) { Line.draw(canvas, primitive) }
else if (typeof(Primitive) == Rect) { Rect.draw(canvas, primitive) }
};
So as you can see, the objects do not automatically select the right method to draw anymore, that's your job now. Therefore the solutions are not equivalent.
But keep in mind that inheritance is not the only way to solve the problem. Pick the one best suited for the job. You should also look at composition which is considered to be more flexible than inheritance by many.
The first example could as easily implemented by using an interface, but consider that there could be methods that are useful for all primitives, e.g. a transformation.
In this case you could do sth. like this:
abstract class Primitive {
protected points;
translate(x, y) {
for point in Points {
point.x = point.x + x;
point.y = point.y + y;
}
}
abstract draw(canvas)
}
By extending the class above all your primitives will have a translate method that will move all points by the given x and y amount.
Best regards,
Frank
More info on Inheritance vs. Composition
language agnostic - Prefer composition over inheritance? - Stack Overflow
https://www.thoughtworks.com/insights/blog/composition-vs-inheritance-how-choose
Added links.
07-19-2016 7:48 PM
07-19-2016 6:48 PM
If you have a superclass with 10 methods "concrete" and 15 methods abstract, and you have subclasses where you only implement these abstract methods and need not reimplementing the 10 concrete methods, would you really instead prefer not using an abstract class and implementing the same code in all 10 methods of all subclasses? I prefer doing the code once.
07-19-2016 7:54 PM
Hi,
Please find my response and scenario below, I was unable to tag your names correctly.
07-19-2016 7:41 PM
Hello All,
Thank you so much, the below try out was what actually made me doubt why and when do we really need abstract class ( programming wise, not conceptual )
A scenario
abstract_class
method display importing info FINAL "common method
abstract method "get info" "method for redefinition
"if we add new abstract method we need to redefine in all classes - Issue
class1 inheriting from abstract_class
redefine method "get info" to "get name info"
class2 inheriting from abstract_class
redefine method "get info" to "get age info"
class_trigger
class-method call_all importing classimp type ref to abstract_class
call method classimp->get_info()
call method classimp->display()
endmethod
create objects class1, class2
class_trigger->call_all ( class1 ).
class_trigger->call_all ( class2 ).
Now, I can do the same using class-method and normal redefinition
Main_class
class-method display importing info "common method
method "get info" ""method for redefinition
class1 inheriting from main_class
redefine method "get info" to "get name info"
class2 inheriting from main_class
redefine method "get info" to "get age info"
class_trigger
class-method call_all importing classimp type ref to abstract_main
call method classimp->get_info()
call method classimp->display()
endmethod
create objects class1, class2
class_trigger->call_all ( class1 ).
class_trigger->call_all ( class2 ).
i think that's what i am trying to know, why go through the trouble of creating abstract classes methods and compel implementing classes to redefine them all.
@Frank kirck , could you please help me understand this scenario and why abstract is needed
07-19-2016 8:49 PM
Hi Madhu,
in your example, both approaches will work just fine.
But...
Abstract classes vs. non abstract base classes
Abstract classes are tools to make coding easier by making it easier to communicate the intent of your code to your fellow programmer.
In your example, if I only look at the code you have, I could try to create an instance of the class Main_class which could work or not depending on the implementation. But if you make the class abstract, I know that the Main_class is not intended to be used directly. This will prevent me from making a mistake.
Abstract classes vs. interfaces
You can achieve that I never try to create an instance of Main_class by making it an interface. But now you force me to implement all methods of Main_class anytime I want to create a new class to be used by the static method. If it is possible to provide meaningful default implementation for some of the methods, it makes sense to provide an abstract base class that implements all these method for me so that I can create a new class with less effort.
Best regards,
Frank
07-20-2016 5:21 AM
07-20-2016 9:04 AM
Frank Krick wrote:
Abstract classes vs. non abstract base classes
Abstract classes are tools to make coding easier by making it easier to communicate the intent of your code to your fellow programmer.
Not just your fellow programmer, but yourself in a few years time! But it's not just to make things easier - it can be part of good design.
I use interfaces for polymorphism mainly, where subclassing hierarchies don't make sense.
If you really want to understand how to use abstract classes, sub classes and interfaces well, I suggest that you get hold of a book of Design Patterns, or research into them.
Note, this is not an ABAP specific issue. It pertains across all OO languages.There are some blogs here that talk about ABAP implementations of design patterns. I suggest searching,
07-20-2016 2:24 PM
07-20-2016 8:11 PM