zoukankan      html  css  js  c++  java
  • Java 基础-接口和多态

    接口

    接口和类的异同

    相同点:

    • 编译后,每个接口跟类都对应一个独立的 .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);
    	}
    }
    
  • 相关阅读:
    OpenStack Paste.ini详解(二)
    OpenStack Paste.ini详解(一)
    PDB调试python代码常用命令
    Devstack 安装OpenStack Pike版本(单机环境)
    Openstack Pycharm 的远程调试
    django Forbidden
    Python 常用命令
    OSI模型和TCP/IP协议族(一)
    ubuntu 下关闭MySql server
    安装ubuntu时的注意事项----个人小总结
  • 原文地址:https://www.cnblogs.com/kika/p/10851526.html
Copyright © 2011-2022 走看看