抽象类和接口的区别:
抽象类(Abstract Class):
- 抽象类是一种不能被实例化的类,它只能被用作其他类的父类(基类)。
- 抽象类可以包含抽象方法和非抽象方法。抽象方法是没有具体实现的方法,需要在子类中被具体实现。非抽象方法则是有具体实现的方法,子类可以直接继承和使用。
- 抽象类可以有构造方法,用于初始化实例对象,但抽象类本身不能被实例化。
- 抽象类可以包含成员变量,也可以包含普通的方法实现。
- 一个类可以继承一个抽象类,因为Java是单继承语言,一个子类只能有一个直接的父类。
抽象类的主要目的是为了提供一种抽象的模板或基础类,它能够定义一些通用的属性和行为,供子类进行继承和实现。抽象类本身不能被实例化,只能作为父类被继承。
接口(Interface):
- 接口是一种纯粹的抽象类型,它用于定义一组方法的规范,但接口本身不提供方法的实现。
- 接口只能包含抽象方法和常量的定义。抽象方法是没有具体实现的方法,需要在实现接口的类中被具体实现。常量则是接口中定义的不可变的值。
- 接口中的方法默认是公有的抽象方法,常量默认是公有的静态常量,不需要显式地声明为public。
- 一个类可以实现多个接口,这是Java支持多继承特性的一种体现。通过实现接口,一个类可以获得多个不同接口的行为。
- 接口不能包含成员变量,但可以定义常量。
接口的主要作用是定义一组行为规范,通过实现接口,类可以获得特定行为的能力,从而实现更高的抽象和多态。
总结一下区别:
- 抽象类是一种部分实现的类,它可以包含具体的方法和抽象方法,主要用于定义共性的行为和属性,无法进行多继承。
- 接口是一种完全抽象的类型,它只能包含抽象方法和常量的声明,主要用于描述对象具有的行为,可以被类多重实现。
在设计和使用类时,需要根据具体情况来选择使用抽象类还是接口。抽象类适用于在多个子类之间有较多重复代码和共同特征的情况下使用,而接口适用于在不相关的类之间定义通用行为要求的情况下使用
案例解释:
一、抽象类(Abstract Class):
抽象类是一种不能被实例化的类,只能被其他非抽象类继承。它主要用于定义一些通用的模板和规范,具体的实现由其子类完成。下面是抽象类的一些特点:
- 抽象类通过关键字abstract来定义,在类的声明前加上abstract即可。
- 抽象类可以包含抽象方法和非抽象方法。
下面是一个简单的示例,通过一个抽象类Animal来定义动物的一些特征和行为:
package LxDemo; /** * @author YJH * @date 2024/1/3 09:29 */ /* * * 1.抽象类必须用 abstract 声明 * (可以单独把Animal,单独写成一个类,为了省事,我写在一个里面) **/ abstract class Animal { protected String name; protected int age; public Animal(String name, int age) { this.name = name; this.age = age; } abstract void makeSound(); // 抽象方法 public void printInfo() { // 非抽象方法 System.out.println("姓名: " + name); System.out.println("年龄: " + age); } } /*2.抽象类需要继承来实现,继承的关键字是extends。*/ class Dog extends Animal { public Dog(String name, int age) { super(name, age); } //抽象类必须实现抽象方法,方法名自己定义 void makeSound() { // 实现抽象方法 System.out.println("汪汪汪!"); } } class Cat extends Animal { public Cat(String name, int age) { super(name, age); } void makeSound() { // 实现抽象方法 System.out.println("喵喵喵!"); } } public class abstractDemo { public static void main(String[] args) { /* * 1.首先,我们定义了一个变量dog,其类型是Animal,这意味着它是一个指向Animal类对象的引用。 * 2.然后,通过调用Dog类的构造函数Dog("旺财", 3)创建一个Dog类的实例对象。 * 3.由于Dog类是Animal类的子类,所以可以将Dog对象赋值给Animal类型的变量dog。 * 4.这样,我们就可以通过dog引用访问Animal类中定义的方法和属性。 * * 需要注意的是,虽然dog引用的是一个Dog类实例对象,但编译器只知道它是 * 一个Animal类型的引用,因此只能调用Animal类中定义的方法和属性。如果 * Dog类重写了Animal类中的某些方法,那么实际执行时将调用Dog类中的方法。 * * 总结:通过将子类对象赋值给父类类型的变量,我们可以实现多态性,并且 * 可以在代码中更灵活地处理对象。这使得我们能够统一对待不同的子类对象,并 *使用相同的方法来处理它们,从而提高代码的可扩展性和可维护性。 */ Animal dog = new Dog("旺财", 3); dog.makeSound(); // 输出:"汪汪汪!" dog.printInfo(); // 输出:"Name: 旺财","Age: 3" //实例化cat对象 Animal cat = new Cat("小花", 2); cat.makeSound(); // 输出:"喵喵喵!" cat.printInfo(); // 输出:"Name: 小花","Age: 2" } }
运行结果:
二、接口(Interface):
接口是一种纯粹的抽象概念,它定义了一些方法的签名(即方法名称、参数列表和返回类型),而不包含具体的实现。接口用于描述对象具有的行为能力,而不关心具体类的实现细节。下面是接口的一些特点:
- 接口通过关键字interface来定义,类似于类的声明。
- 接口中只能包含常量和抽象方法。
以下是一个简单的示例,通过接口Shape来定义形状对象的一些行为:
package LxDemo; /** * @author YJH * @date 2024/1/3 09:49 */ //利用interface定义一个接口 interface Shape { //计算数字和 int addition(); //计算数字差 int subtraction(); } //利用implements,实现接口 class Circle implements Shape { private int radius; int a = 10; public Circle(int radius) { this.radius = radius; } public int addition() { // 实现接口中的方法 return a + radius; } public int subtraction() { // 实现接口中的方法 return a - radius; } } //利用implements,实现接口 class Rectangle implements Shape { private int snum; private int munm; public Rectangle(int snum, int munm) { this.snum = snum; this.munm = munm; } public int addition() { // 实现接口中的方法 return snum + munm; } public int subtraction() { // 实现接口中的方法 return (snum - munm); } } public class inteFaceDemo { public static void main(String[] args) { Shape circle = new Circle(5); System.out.println("10 + 5 = " + circle.addition()); System.out.println("10 - 5 = " + circle.subtraction()); Shape rectangle = new Rectangle(3, 4); System.out.println("3 + 4 = " + rectangle.addition()); System.out.println("3 - 4 =" + rectangle.subtraction()); } }
运行结果: