Предпочитают абстрактные базовые классы в следующих сценариях:
- Базовый класс не может существовать без подкласса => базовый класс просто абстрактный и его нельзя создать.
- Базовый класс не может иметь полную или конкретную реализацию метода => Реализация метода в том случае, если базовый класс неполон, и только подклассы могут обеспечить полную реализацию.
- Базовый класс предоставляет шаблон для реализации метода, но он все еще зависит от конкретного класса, чтобы завершить реализацию метода - Template_method_pattern
Простой пример, иллюстрирующий вышеприведенные пункты
Shape
является абстрактным и не может существовать без конкретной формы, такой как Rectangle
. Рисование Shape
не может быть реализовано в классе Shape
, поскольку разные формы имеют разные формулы. Лучший вариант для обработки сценария: оставить реализацию draw()
для подклассов
abstract class Shape{
int x;
int y;
public Shape(int x,int y){
this.x = x;
this.y = y;
}
public abstract void draw();
}
class Rectangle extends Shape{
public Rectangle(int x,int y){
super(x,y);
}
public void draw(){
//Draw Rectangle using x and y : length * width
System.out.println("draw Rectangle with area:"+ (x * y));
}
}
class Triangle extends Shape{
public Triangle(int x,int y){
super(x,y);
}
public void draw(){
//Draw Triangle using x and y : base * height /2
System.out.println("draw Triangle with area:"+ (x * y) / 2);
}
}
class Circle extends Shape{
public Circle(int x,int y){
super(x,y);
}
public void draw(){
//Draw Circle using x as radius ( PI * radius * radius
System.out.println("draw Circle with area:"+ ( 3.14 * x * x ));
}
}
public class AbstractBaseClass{
public static void main(String args[]){
Shape s = new Rectangle(5,10);
s.draw();
s = new Circle(5,10);
s.draw();
s = new Triangle(5,10);
s.draw();
}
}
выход:
draw Rectangle with area:50
draw Circle with area:78.5
draw Triangle with area:25
Выше код охватывает точку 1 и точку 2. Вы можете изменить метод draw()
как шаблонный метод, если базовый класс имеет некоторую реализацию и вызывает метод подкласса для завершения draw()
функции.
Теперь тот же пример с шаблоном метода Template:
abstract class Shape{
int x;
int y;
public Shape(int x,int y){
this.x = x;
this.y = y;
}
public abstract void draw();
// drawShape is template method
public void drawShape(){
System.out.println("Drawing shape from Base class begins");
draw();
System.out.println("Drawing shape from Base class ends");
}
}
class Rectangle extends Shape{
public Rectangle(int x,int y){
super(x,y);
}
public void draw(){
//Draw Rectangle using x and y : length * width
System.out.println("draw Rectangle with area:"+ (x * y));
}
}
class Triangle extends Shape{
public Triangle(int x,int y){
super(x,y);
}
public void draw(){
//Draw Triangle using x and y : base * height /2
System.out.println("draw Triangle with area:"+ (x * y) / 2);
}
}
class Circle extends Shape{
public Circle(int x,int y){
super(x,y);
}
public void draw(){
//Draw Circle using x as radius ( PI * radius * radius
System.out.println("draw Circle with area:"+ ( 3.14 * x * x ));
}
}
public class AbstractBaseClass{
public static void main(String args[]){
Shape s = new Rectangle(5,10);
s.drawShape();
s = new Circle(5,10);
s.drawShape();
s = new Triangle(5,10);
s.drawShape();
}
}
выход:
Drawing shape from Base class begins
draw Rectangle with area:50
Drawing shape from Base class ends
Drawing shape from Base class begins
draw Circle with area:78.5
Drawing shape from Base class ends
Drawing shape from Base class begins
draw Triangle with area:25
Drawing shape from Base class ends
Как только вы решили, что вы должны сделать как метод abstract
, у вас есть два варианта: либо пользовательский interface
, либо abstract
класс. Вы можете объявить ваши методы в interface
и определить abstract
класс как класс, реализующий interface
.