在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。 在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
抽象类
不该被创建的对象。
Animal
仅是一种会吃会睡的对象,再无其他行为,不够具体,不够完整。
程序是用来模拟现实世界、解决现实问题的。现实世界中存在的都是“动物”具体的子类对象,并不存在“动物”对象。
所以,Animal
不应该被独立创建成对象。
如何限制这种对象的创建呢?便引入了抽象类的概念。
应用:
abstract
修饰类,此类不能new
对象
public class Main {
public static void main(String[] args) {
//Animal是抽象的,无法实例化
Animal animal = new Animal();//会报错
}
}
//被abstract修饰的类,被称为抽象类
abstract class Animal {
String breed;
int age;
public void eat() {
System.out.println("动物在吃");
}
}
作用:
- 可被子类继承,提供共性的属性的方法。
- 可声明为引用,更自然地使用多态。
经验:
- 抽象父类,可作为子类的组成部分。
- 依附于子类对象存在。
- 有父类共性+子类独有组成完整的子类对象。
抽象方法
不该被实现的方法
需求:
Dog
中eat()
应输出“狗在吃骨头”。Cat
中eat()
应输出“猫在吃鱼”。
父类中提供的方法很难满足子类的需求:
- 如不定义,则表示所有动物都不会吃。
- 如定义,则略显多余,多数会被子类覆盖。
被
abstract
修饰的方法,被称为抽象方法。
只有方法声明,没有方法实现({}部分)。
意为不完整的方法,必须包含在抽象类中。
抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类。
产生继承关系后,子类必须重写父类中所有的抽象方法,否则子类还是抽象类。
实现接口中的抽象方法时,访问修饰符必须是public
。
C++中的抽象
C++中通过声明至少一个纯虚拟成员函数来创建抽象类。 这是使用 pure 说明符 () 语法声明的虚函数= 0。 派生自抽象类的类必须实现纯虚函数或者它们必须也是抽象类。
请考虑虚函数中所述的示例。 类 Account 的用途是提供通用功能,但 Account 类型的对象太通用,因此没什么用。 这表示 Account 是抽象类的很合适的候选项:
// deriv_AbstractClasses.cpp
// compile with: /LD
class Account {
public:
Account( double d ); // Constructor.
virtual double GetBalance(); // Obtain balance.
virtual void PrintBalance() = 0; // Pure virtual function.
private:
double _balance;
};
接口
接口是一组行为的规范、定义,没有实现。
- 没有构造方法,不能创建对象。
- 只能定义:公开静态常量、公开抽象方法。
//使用interface关键字定义接口
public interface MyInterface {
//没有构造方法,不能创建对象
//只能定义:公开静态常量、公开抽象方法
public String NAME = "Interface";
public abstract void method();
}
与抽象类的异同
相同:
- 可编译成字节码文件。
- 不能创建对象。
- 可以作为引用类型。
- 具备Object类中所定义的方法。
不同:
- 所有属性都是公开静态常量,隐式使用
public static final
修饰。 - 所有方法都是公开抽象方法,隐式使用
public abstract
修饰。 - 没有构造方法、动态代码块、静态代码块。
什么是接口
接口是一种能力和约定。
接口的定义:代表了某种能力。
方法的定义:能力的具体要求。
经验:Java为单继承,当父类的方法种类无法满足子类需求时,可实现接口扩充子类能力。
接口支持多实现,可为类扩充多种能力。
- 类跟类之间的继承,我们叫做继承某一个类。
- 接口之间,通常叫做实现某一个或某几个接口。
JDK8新特性:接口中的默认方法
默认方法可以有多个,可以被所有实现类继承。
使用default
修饰的方法,可以有实现。
public class Main {
public static void main(String[] args) {
Test test = new Test();
test.print();
test.eat();
}
}
class Test implements IEat {
@Override
public void print() {
System.out.println(NUM);
}
}
//I打头,命名规范
interface IEat {
int NUM = 10;//常量
void print();//抽象方法
default void eat() {
System.out.println("Default Method");
}
}
接口之间的多继承。
Java类只能单继承,但接口之间可以多继承,一个类也可以实现多个接口。
public class Main {
public static void main(String[] args) {
Test test = new Test();
test.print();
}
}
//接口可以多继承
class Test implements Itest1, Itest2 {
@Override
public void print() {
System.out.println(NUM);
}
}
//I打头,命名规范
interface Itest1 {
int NUM = 10;//常量
}
interface Itest2 {
void print();
}
常量接口
将多个常用于表示状态或固定值的变量,以静态常量的形式定义在接口中统一管理,提高代码可读性。
interface Constant {
String USERNAME = "WuShF";
String URL = "csdn.wushf.top";
String QQ = "1481542813"
}
接口小结
- 定义一个接口,使用
interface
关键字。 - 在一个接口中,只能定义常量、抽象方法。JDK1.8之后可以定义默认的实现方法。
- 接口可以继承多个接口:
extend XXX, XXX
。 - 一个具体类实现接口使用
implements
关键字。 - 一个类可以实现多个接口。
- 抽象类实现接口可以不实现接口的方法。
- 在接口中定义的方法的访问修饰符,默认为
public
。 - 接口不能有构造方法,不能被实例化。