Java中抽象类和接口
抽象类和接口
- 抽象类
- 抽象类的概念
- 抽象类的使用
- 接口
- 接口的概念
- 接口的使用
- 接口使用注意事项
- 实现多个接口
- 接口和抽象类的区别
抽象类
抽象类的概念
面向对象语言中所有对象都是用类来描述的,如果在类中没有详细的描述一个具体对象,这就可以被称为抽象类
就像定义了一个Shape图形的类,但是我们并不知道是什么图形,是三角形、还是圆形等等
这里明显是继承关系,都有一个draw方法,子类重写这个draw方法,父类Shape并不需要具体描述打印那个图形,可以通过子类来确认具体的描述,因此这里的Shape父类就可以被设计成" 抽象类 " 这里的draw方法没有实际的工作,也可以被设计为" 抽象方法 "
抽象类的使用
抽象类如何定义呢?
Java中被 abstract修饰称为抽象类,抽象类中被 abstract修饰的⽅法称为抽象⽅法,抽象⽅法不⽤给出具体的实现体。
例如:
//抽象类
public abstract class Shape{
public int a = 10;
//抽象方法
abstract public void draw();
abstract void draw1();
//成员方法
public void test(){
}
//构造方法
public Shape(){
}
}
抽象类也是类可以有抽象方法,也可以有成员变量和成员方法,甚至是构造方法
抽象类中不⼀定包含抽象⽅法,但是有抽象⽅法的类⼀定是抽象类
抽象类的使用注意事项
1.但是这里的抽象类中的抽象方法不可以有具体如何实现的
2.抽象类中的抽象方法不可以被private修饰
3.抽象类中的抽象方法不可以被final和static所修饰 ,因为这里由于父类的抽象方法不可以具体描述,因此需要借助子类重写来具体实现,但是被final和static所修饰的方法是不可以被重写的
4.抽象类必须被继承,子类要重写父类中的抽象方法,如果不想要重写要在方法前面加上abstract修饰,让子类中这个方法变成抽象类,但是如果有其他类继承这个子类的话,这个方法还是要被重写
这里如果如果继承了抽象类,不重写抽象类中的抽象方法,编译器会报错
因此需要重写
abstract class Shape{
abstract public void draw();
}
class Tra extends Shape{
//重写
@Override
public void draw() {
System.out.println("画一个三角形");
}
}
如果不想重写那子类就必须被abstract修饰变成抽象类
abstract class Shape{
abstract public void draw();
}
abstract class Tra extends Shape{
}
5.抽象类无法实例化对象,借助子类对象
我们以上面的Shape抽象类来举例如何使用
abstract class Shape{
abstract public void draw();
}
class Tra extends Shape{
@Override
public void draw() {
System.out.println("画一个三角形");
}
}
class Cycle extends Shape{
@Override
public void draw() {
System.out.println("画一个圆形");
}
}
public class Test {
public static void main(String[] args) {
//抽象类不可以实例化对象
//需要借助子类
//向上转型
Shape shape = new Cycle();
Shape shape1 = new Tra();
shape.draw();
shape1.draw();
}
}
上面抽象类只能借助继承它的子类进行实例化,不可以直接自己实例化对象,这里也用到了多态的思想,进行实例化和访问
运行结果如下
我们发现了抽象类和以前的普通类的区别不大,以前普通类也可以继承也可以重写父类的方法,也可以发生多态,那我们为什么要使用abstract抽象类方法
因为就是增加编译器校验,就像在普通类中可以实例化父类对象,但是在抽象类中不可以,所以如果写错,编译器可以帮助我们尽快找到问题
接口
接口的概念
接口其实生活中处处都是,例如:手机充电接口、生活中插板等等
生活中的插板是可以插好多电器,这些电器必须是符合标准要求的
Java中接口可以被看成为多个类的公共规范 ,其他类可以引用这个接口
语法规则
和定义基本类相同,就是把class关键字换成interface关键字就行了
public interface 接⼝名称{
// 抽象⽅法
}
//接口定义
public interface Animal{
public abstract void methodA();//1
abstract void methodB();//2
public void methodC();//3
void methodD();//4
}
上面这4个定义方法是一样的,如果前面不写,编译器会默认为public abstract类型,一般使用第四种,因为这样比较简洁
接口的使用
接口是不可以直接使用的,必须有一个类来实现这个接口,实现接口中的所有抽象方法
接口的使用方法
public class 类名称 implements 接⼝名称{
// 接口中抽象类的实现
//……等其他变量和方法
}
下面有个例子,就是实现一个手机打开和关闭接口收件软件的简单例子
//接口
public interface Phone {
//打开手机软件
void openDevice();
//关闭
void closeDevice();
}
//音乐软件实现接口
public class Music implements Phone{
@Override
public void openDevice() {
System.out.println("播放音乐");
}
public void listenMusic(){
System.out.println("听音乐");
}
@Override
public void closeDevice() {
System.out.println("关闭音乐");
}
}
//拍照软件实现接口
public class Photo implements Phone{
@Override
public void openDevice() {
System.out.println("打开相机");
}
public void takePhoto(){
System.out.println("拍照片");
}
@Override
public void closeDevice() {
System.out.println("关闭相机");
}
}
//使用手机类
public class UsePhone {
public void open(){
System.out.println("打开手机-----");
}
public void close(){
System.out.println("关闭手机------");
}
//这里的Mushic和Photo都是靠Phone这个接口
//这里可以实现多态
public void useDevice(Phone phone){
//打开相对于软件
phone.openDevice();
//判断进入了那个软件,就执行那个软件特有功能
if(phone instanceof Photo){
//向下转型
Photo photo = (Photo) phone;
//拍照功能
photo.takePhoto();
}
if(phone instanceof Music) {
Music music = (Music) phone;
//放音乐功能
music.listenMusic();
}
//关闭软件
phone.closeDevice();
}
}
public class Test {
public static void main(String[] args) {
//Phone phone = new Phone();
//接口是一种类型不能直接new新对象
UsePhone usePhone = new UsePhone();
//打开手机
usePhone.open();
//进入相对于的软件
usePhone.useDevice(new Music());//音乐
usePhone.useDevice(new Photo());//拍照
//关闭手机
usePhone.close();
}
}
这里有个Phone接口,和两个子类Music和Photo来实现接口,和一个UsePhone来使用其手机
运用了多态的特征来实现这个手机功能
运行结果如下
接口使用注意事项
1.接口中方法都是默认是抽象的,因为抽象方法是不可以有主体的,接口中的方法只能由实现接口类实现
如果有主体编译器会报错
2.接⼝类型是⼀种引⽤类型,但是不能直接实例化接⼝的对象
但是可以通过子类来实例化对象
interface Phone {
//打开手机软件
void openDevice();
//关闭
void closeDevice();
}
class Music implements Phone{
@Override
public void openDevice() {
System.out.println("播放音乐");
}
public void listenMusic(){
System.out.println("听音乐");
}
@Override
public void closeDevice() {
System.out.println("关闭音乐");
}
}
public class Test {
public static void main(String[] args) {
//Phone phone = new Phone();//错误的
Phone phone = new Music();
//打开
phone.openDevice();
//强制类型转化,向下转型才可以访问
//子类中特由的方法,和抽象类相同
Music music = (Music)phone;
music.listenMusic();
//关闭
phone.closeDevice();
}
}
运行结果如下
3.接口中的变量会被隐式为public static final 变量
interface Phone {
//打开手机软件
int a = 10;
void openDevice();
//关闭
void closeDevice();
}
public class Test {
public static void main(String[] args) {
System.out.println(Phone.a);
//Phone.a= 10;//错误的被final修饰的是不可以修改的
}
}
静态的变量是通过类名来访问的,这里接口中的a是可以直接使用类名来访问,所以接口中的变量默认是public static final 修饰
运行结果如下
4.接口中不可以有初始化程序,就像实例代码块、静态代码块和构造方法等等
实现多个接口
Java虽然不支持多继承(就是一个子类有多个父类),但是支持多个接口
interface Running{
void run();
}
interface Swimming{
void swim();
}
//一个Dog类来实现多个接口
class Dog implements Running,Swimming{
public String name;
public Dog(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(this.name+"跑步");
}
@Override
public void swim() {
System.out.println(this.name+"游泳");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog("小七");
dog.run();
dog.swim();
}
}
上面使用Dog类来同时实现Running和Swimming这两个接口,但如果这两个是普通类就不可以多继承
运行结果如下
既然可以多个接口,那可以继承和实现多个接口一起吗
例如
//父类
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
}
//接口
interface Fly{
void fly();
}
interface Running{
void run();
}
interface Swimming{
void swim();
}
//继承了Animal类,和一些接口
class Dog extends Animal implements Running,Swimming{
public Dog(String name){
super(name);
}
@Override
public void run() {
System.out.println(this.name+"跑步");
}
@Override
public void swim() {
System.out.println(this.name+"游泳");
}
}
这上面就是一个类继承了一个父类,同时实现多个接口
那可以接口继承接口
interface Running{
void run();
}
interface Swimming{
void swim();
}
//接口继承接口
interface Animal extends Running,Swimming{
}
//继承了Animal类,和一些接口
class Dog implements Animal{
public String name;
public Dog(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(this.name+"跑步");
}
@Override
public void swim() {
System.out.println(this.name+"游泳");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog("旺财");
animal.run();
animal.swim();
}
}
这里表示一个Animal接口来继承Running和Swimming这两个接口,表示一个动物既可以跑步也可以泳游,如果有类实现Animal接口,就需要把这个Animal接口以及其继承的Running和Swimming接口都要实现,相当于接口之间的合并
运行结果如下
接口和抽象类的区别
最主要的区别就是 抽象类中可以有普通方法和字段,不是只有抽象方法,而接口中不能包含普通方法和字段(代码块),子类需要重写所有的抽象方法
到这里就结束了,希望对大家有所帮助,预知后事如何,请听下回分解