Java 基础-接口和多态

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kikajack/article/details/84925531

接口

接口和类的异同

相同点:

  • 编译后,每个接口跟类都对应一个独立的 .class 字节码文件
  • 字节码文件必须包含在与包名匹配的目录结构中

不同点:

  • 接口没有构造方法,不可实例化
  • 接口中的所有方法都必须是抽象方法
  • 接口不能包含成员变量,除了 static 和 final 变量
  • 接口不是被类继承,而是被类实现
  • 接口支持多继承

接口中的所有方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。

语法

[可见度] interface 接口名称 [extends 其他的接口名名] {
        // 声明变量
        // 抽象方法
}

示例:

interface I {
    double PI=3.14; // public final 可以省略
    void printPi(); // public abstract 可以省略
    public abstract void printPi2();
}
public class Test implements I{
    public static void main(String[] args) {
        System.out.println(PI);
        PI++; // 接口属性不可修改,否则报错:cannot assign a value to final variable PI
        Test t = new Test();
        t.printPi();
    }
    // 要实现接口的方法,只能是 public,否则编译报错
    public void printPi() {
        System.out.println(PI);
    }
    // 这里没有实现 printPi2,编译报错
}

多态

类型转换

转换类型

根据数据类型,可以分为两类:

  • 基本类型转换:将值从一种类型转换成另一种类型
  • 引用类型转换:将引用转换为另一种类型的引用,不改变对象本身的类型

根据是否自动进行,也分为两类:

  • 自动转换:编译器自动执行,例如加号操作符一侧有String类型时,另一侧自动转为String
  • 显式(强制)转换:代码中指定要转换到的类型,例如 (int)3.14(Manager)emp

引用类型转换时,只能被转为:

  • 任一个超类或接口(向上转换),转换后可用的接口受限
  • 引用指向的对象的类型(唯一可以向下转型的情况)

示例:

Employee emp;
Manager man; // Manager 继承自 Employee
emp = new Manager(); // 自动向上转换,但实际类型不变
man = (Manager)emp; // 向下转换

方法查找

  • 类方法查找:静态方法属于整个类,不属于任何对象,所以总是在引用变量声明时所属的类中进行查找
  • 实例方法查找:从对象创建时的类开始,依次向上查找

多态

在实现了统一接口或从相同父类派生出来的不同类型的对象中,执行同一个方法时,会有不同的表现。

例如所有 Object 类的对象都可以响应 toString 方法,但是表现不同。

绑定

绑定:将方法调用与方法体结合起来。根据绑定时期的不同,可以分为:

  • 早绑定:程序运行之前(编译时)执行绑定
  • 晚绑定:程序运行时,基于对象类别,绑定应该执行的方法体,也叫动态绑定

动态绑定示例:

abstract class Shape {
	public abstract void draw();
}
class Circle extends Shape {
	public void draw() {
		System.out.println("Circle draw");
	}
}
class Rectangle extends Shape {
	public void draw() {
		System.out.println("Rectangle draw");
	}
}
public class Test {
	public static void main(String[] args) {
		Shape[] s = new Shape[6];
		for (int i = 0; i < s.length; i++) {
			s[i] = Math.random()*2 > 1 ? new Circle() : new Rectangle();
		}
		for (int i = 0; i < s.length; i++) s[i].draw();
	}
}

上面的例子,引入了随机数,编译时无法确定对象数组中的每一个对象的具体类型,需要在执行时动态绑定。每次执行的结果都不一样。

多态示例二:

abstract class Vehicle {
    private String type;
    public String getType(){return this.type;}
}
class Bus extends Vehicle {
    public String getType(){return "bus";}
}
class Car extends Vehicle {
    public String getType(){return "car";}
}
abstract class Driver {
	public abstract void drives(Vehicle v);
}
class MaleDriver extends Driver {
	public void drives(Vehicle v) {
		System.out.println("a man drives a " + v.getType());
	}
}
class FemaleDriver extends Driver {
	public void drives(Vehicle v) {
		System.out.println("a woman drives a " + v.getType());
	}
}
public class Test {
	public static void main(String[] args) {
		Driver a = new MaleDriver();
		Driver b = new FemaleDriver();
		Vehicle x = new Bus();
		Vehicle y = new Car();
		a.drives(x);
		b.drives(y);
	}
}

多态示例二(二次分发,将请求进行两次分发):

abstract class Vehicle {
    private String type;
    public abstract void drivedByMale();
    public abstract void drivedByFemale();
}
class Bus extends Vehicle {
    public void drivedByMale() {
        System.out.println("a man drive a bus");
    }
    public void drivedByFemale() {
        System.out.println("a woman drive a bus");
    }
}
class Car extends Vehicle {
    public void drivedByMale() {
        System.out.println("a man drive a car");
    }
    public void drivedByFemale() {
        System.out.println("a woman drive a car");
    }
}
abstract class Driver {
	public abstract void drives(Vehicle v);
}
class MaleDriver extends Driver {
	public void drives(Vehicle v) {
	    v.drivedByMale();
	}
}
class FemaleDriver extends Driver {
	public void drives(Vehicle v) {
	    v.drivedByFemale();
	}
}
public class Test {
	public static void main(String[] args) {
		Driver a = new MaleDriver();
		Driver b = new FemaleDriver();
		Vehicle x = new Bus();
		Vehicle y = new Car();
		a.drives(x);
		b.drives(y);
	}
}

猜你喜欢

转载自blog.csdn.net/kikajack/article/details/84925531