一、抽象类和接口定义和使用场景
当你需要设计一些类,这些类有一些属性和方法是可以共享的,但同时又有一些属性和方法是需要不同的。在这种情况下,Java中提供了两种不同的机制,即“抽象类”和“接口”。
抽象类是一个类,它不能被实例化,而是需要被子类继承。抽象类可以包含抽象方法,这些方法没有具体的实现,只有方法名。当然,抽象类中也可以包含具有实现的方法。子类继承抽象类时,必须实现抽象方法,否则子类也必须标记为抽象类。
接口也是一种抽象类,但它只包含常量和抽象方法的定义。所有接口方法都是抽象的,没有实现部分。类可以实现一个或多个接口,这意味着类必须实现接口中定义的所有方法。接口提供了一种使用多态性编程的方法,即使不知道对象属于哪个类,也可以调用对象的方法。
总的来说,抽象类和接口都可以用来为类提供共享的属性和方法。抽象类允许具体方法而接口则只有抽象方法。如果你需要为一组相关的类提供通用的属性和方法,你应该选择抽象类。如果你需要实现多态性或在不同的类中实现相同的方法,你应该选择接口。
二、注意点
抽象类中可以有实现方法。抽象类中可以包含有具体实现的方法,这些方法可以在子类中继承和使用,也可以在抽象类本身中调用使用。抽象类中的具体实现方法可以在子类中被重写或者继承,也可以被子类调用或者使用。在抽象类中定义具体实现方法可以为子类提供一些共性的方法,用于子类继承和调用,从而简化了子类的实现。
以下是Java的一个抽象类和接口的示例代码:
//抽象类定义 shape
abstract class Shape {
protected int x, y;
public void move(int x, int y) {
this.x = x;
this.y = y;
}
public abstract void draw();
}
//接口定义 Polygon
interface Polygon {
public void getNumberOfSides();
}
//Triangle 继承 Shape,实现 Polygon
class Triangle extends Shape implements Polygon {
private int sides = 3;
public void draw() {
System.out.println("Drawing Triangle...");
}
public void getNumberOfSides() {
System.out.println("Number of sides: " + sides);
}
}
//Rectangle 继承 Shape,实现 Polygon
class Rectangle extends Shape implements Polygon {
private int sides = 4;
public void draw() {
System.out.println("Drawing Rectangle...");
}
public void getNumberOfSides() {
System.out.println("Number of sides: " + sides);
}
}
//主函数类
public class Main {
public static void main(String[] args) {
//Shape 形状1
Shape shape1 = new Triangle();
shape1.move(10, 20);
shape1.draw();
Polygon poly1 = new Triangle();
poly1.getNumberOfSides();
//Shape 形状2
Shape shape2 = new Rectangle();
shape2.move(50, 100);
shape2.draw();
Polygon poly2 = new Rectangle();
poly2.getNumberOfSides();
}
}
在以上代码中,Shape
类是抽象类,Polygon
接口具有 getNumberOfSides
方法。Triangle
类和 Rectangle
类都继承了 Shape
类并实现了 Polygon
接口。
在 Main
类的 main
方法中,我们实例化了 Triangle
和 Rectangle
的对象,并调用了它们的 draw
和 getNumberOfSides
方法。由于 Shape
类是抽象类,因此我们无法直接实例化它本身。
具体来说 “抽象类中可以有普通的方法,这些方法可以有实现代码,不一定是抽象方法。”这种情况下,这些普通方法可以直接被子类继承和使用,子类可以选择不覆盖这些方法,也可以选择覆盖这些方法,实现多态的效果。
举个例子,比如抽象类Animal表示一个动物,有一个普通方法eat(),表示动物的进食行为。如果我们的具体动物类如Dog、Cat、Bird等都可以使用这个方法,我们在Animal类中就可以实现它,而不必让每个具体类都来实现这个功能。在这种情况下,eat()方法可以在Animal类中定义实现代码,这样所有继承Animal类的子类就可以直接继承这个方法,而无需再次编写它。如果某个具体类需要特殊的eat()行为,它可以选择覆盖这个方法。这种情况下,Animal类就成为了一个带有可扩展功能的类。
Animal类中的eat()方法是一个普通方法,不属于抽象方法。抽象方法是没有实现的方法,而普通方法是有实现代码的方法。在Animal类中,如果我们需要定义一个默认的eat()方法实现,可以直接在方法中添加实现代码,而不需要用abstract关键字来声明它是一个抽象方法。当然,如果我们希望让某些特定的子类必须去覆盖eat()方法,那么我们可以将eat()方法声明为抽象方法,以强制子类去实现它。