java第四节 类的继承/抽象/接口/多态性
/* 类的继承 类的继承可以简化类的定义 java只支持单继承,不允许多重继承 可以有多层继承,即一个类可以继承其一个类的子类,如类B继承了类A,类C又可以继承类B 那么类C也间接继承了类A 子类继承父类所有的成员变量和成员方法,但不继承父类的构造方法, 在子类的构造方法中可使用语句super(参数列表) 调用父类的构造方法 如果子类的构造方法中没有显式地调用父类构造方法,也没用使用this关键字调用重载的其它构造方法,则在产生子类的实例对象时 系统默认调用父类无参数的构造方法 子类对象的实例化过程 1 分配成员变量的存储空间并进行默认的初始化,就是用new关键字产生对象后 对类中的成员变量按第三章的表3.1的对应关系对对象中的成员变量进行初始化赋值 2 绑定构造方法参数,就是new Person(实际参数列表)中所传递进的参数赋值给构造方中的形式参数变量 3 如果有this()调用,则调用相应的重载构造方法(被调用的重载构造方法又从步骤2开始执行这些流程) 被调用的重载构造方法的执行流程结束后,回到当前构造方法,当前构造方法直接跳转到步聚6执行 4 显示或隐式追溯调用父类的构造方法(一直到Ojbect类为止,Object是所有java类的最顶层父类) 在本音后面部分有详细讲解,父类的构造方法又从步骤2开始对父类执行这些流程,父类的构造方法的执行流程结束后,回到当前构造方法,当前构造方法继承往下执行 5 进行实例变量的显示初始化扣喺,也就是执行在定义成员变量时就对其进行赋值的语句 6 执行当前构造方法的方式体中的程序代码 1):为什么super()和this()调用语句不能同时在一个构造函数中出现? 因为当在一个构造函函数中出现this()调用以后,那么去别外一个构造函数将也会直接默认或指定的super()方法 如要执行完成以后,返回到初始的构造函数还让执行super()方法时,那就又是重复操作了,无意义 所以编译也不会通过的 2):为什么super()和this()调用语句只能作为构造函数的第一句出现 如果不是作为第一句出现,编译也会出错的 如果选执行一些赋值语句,然后执行this或super()函数 那么就跟我们的执行流程相矛盾了 因为构造函数需要需要执执行this,如果没有this执行super()方法 编译器也不会让通过的 覆盖父类的方法 覆盖方法必须和被覆盖方法具有相同的方法名称,参数列表和返回值类型 如果在子类中想调用父类中那个被覆盖的方法,我们可以用super方法的格式 覆盖方法时,不能使用此父类中被覆盖的方法更严格的访问权限 final关键字 1 在java中声明类,属性和方法时,可以使用关键字final来修饰 2 final标记的类不能被继承 3 final标记的方法不能被子类重写 4 final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次 5 方法中定义的内置类只能访问该方法内的final类型的局部变量 用final定义的局部变量相当于是一个常量,它的生命周期超出了方法运行的重命周期 将一个行参定义成final也是可以的,这就是限定了我们在方法中修改形式参数的值 6 public static final共同标记常量时,这个常量就成了全局常量 抽象类 java中可以定义一些不含方法体的方法,它的方法体的实现交给该类的子类根据自己的情况去实现 这样的方法就是抽象方法,包含抽象方法的类叫做抽象类 1 抽象类必须使用abstract关键字来修饰,抽象方法也必须用abstract来修饰 2 抽象类不能被实例化,也就是不能用new关键字去产生对象 3 抽象类只需声明,而不需实现 4 含有抽象方法的类必须声明为抽象类,抽象类的子类必须覆盖所有抽象方法后才能被实例化,否则这个子类还是个抽象类 */ //final class Person 将不能被继承了 class Person { //protected final String name = "unknown"; 变量为final时将不能被子类赋值了 protected String name = "unknown"; //public final String x = "abc"; //第一种赋值是初始赋值 public final String x; //public static final String x; public static final String y = "abc"; public int age = -1; public Person() { this.x = "cde"; } public Person(String name, int age) { this.name = name; this.age = age; //或者在构造函数中进行赋值 this.x = "abc"; } //public void getInfo(){} 将不能在子类重写了 public void getInfo() { //this.x = "abc"; //用final定义的变量将不能被修改了 System.out.println("name:"+name+", age:"+age); } }; class Student extends Person { public String school = "unknown"; public Student() { //super("xlc",15); super(); } public Student(String name, int age, String school) { this(name,age); //调用自己的构造函数 this.school = school; //this(name,age); //调用自己的构造函数 } public Student(String name, int age) { super(name, age); } public void getInfo() { System.out.println("school:"+school+"name:"+name+", age:"+age); super.getInfo(); } public void study() { } }; class TestStudent { public static void main(String[] args) { //Student st = new Student(); //st.name = "xlc"; //st.age = 34; //st.getInfo(); Student st = new Student("xlc",22,"清华大学"); st.getInfo(); System.out.println(Float.MAX_VALUE); } };
/* 接口(interface) 如果一个抽象类中的所有方法都是抽象的,我们就可以将这个类用另外一种方式来定义,也就是接口定义 接口是抽象方法和常量值的定义的集合,从本质上讲,接口是一种特殊的抽象类 这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现 1 接口中的成员都是public访问类型的,接口的变量默认是用public static final标识的 2 我们可以定义一个新的接口用extends 关键字去继承一个已有的接口 3 我们也可以定义一个类用implements关键字去实现一个接口中的所有方法,我们还可以去定义一个抽旬类用implements关键字去实现一个接口中定义的部分方法 4 一个类可以继承一个父类的同时,实现一个或多个接口,extneds关键字必须位于implements关键字之前 对象的类型转换 1 子类对象可以自动转换成父类 2 父类转换为子类必须使用强制转换 3 instanceof操作符可以用它来判断一个实例对象是否属于一个类 4 Object类及equals方法 */ /*abstract class A { abstract int aa(int x, int y); //抽象类将不能实例化 }; class B extends A { int aa(int x, int y) { return 1; } };*/ interface Runner { int ID = 1; void run(); } interface Animal extends Runner { void breathe(); } class Fish implements Animal { public void run() { System.out.println("fish is swimming"); } //public void breathe() public void breathe() { System.out.println("fish is bubbling"); } public static void main(String[] args) { Fish f = new Fish(); int j=0; j = Runner.ID; j = f.ID; //f.ID = 2; //常量不能被赋值 } }; abstract class LandAnimal implements Animal { public void breathe() { } }; interface dog { void uaau(); } interface Flyer { void fly(); } class Bird implements Runner, Flyer { public void run() { } public void fly() { } }; //继承一个类时,可以实现其它接口 //也是可以继承从外接口类的 class Student extends Person implements Runner, dog //如果继承类和接口,extends必须在implements之前 { public void run() { } public void uaau() { } }; interface A { //public static final int ID=1; //int ID = 1; //这个是一个常量而不是一个变量,接口只能定义常量,不能定义变量, //只能定义常量和抽象类 public static final int ID=1; int aa(int x, int y); void bb(); } /*class { public static void main(String[] args) { System.out.println("Hello World!"); } }*/
/* 面向对象的多态性 1):应用程序不必为每一个派生类(子类)编写功能调用 只需要对抽象基类进行处理即可,这一招叫"以不变应万变",可以大大提高程序的可复用性 2):派生类的功能可以被基类的引用变量引用,这叫向后兼容,可提高程序的可扩充性和可维护性 以前写的程序可以被后来程序调用不足以为奇,现在写的程序(如callA方法)能调用以后写的程序(以后编写的一个类A的子类,如类D)就了不起了 */ class A { public void func1() { System.out.println("A func1 is calling"); } public void func2() { func1(); } }; class B extends A { public void func1() { System.out.println("B func1 is calling"); } public void func3() { System.out.println("B func3 is calling"); } }; class C { public static void main(String[] args) { B b = new B(); callA(b); //A aa = b; //callA(new A()); } public static void callA(A a) { /*if(a instanceof B) { B b = (B)a; //强制类型转换 b.func1(); b.func2(); b.func3(); }else{ a.func1(); a.func2(); }*/ a.func1(); a.func2(); //a.func1(); //a.func2(); //a.func3(); } }; class Student extends Object { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } /*public boolean equals(Object obj) { Student st = null; if(obj instanceof Student) { st = (Student)obj; if(st.name == name && st.age == age) { return true; } else{ return false; } }else{ return false; } }*/ //如果没有覆盖父类的equals方法,那么将返回不等 //只是重载了一下函数 public static void main(String[] args) { Student st1 = new Student("张三",20); Student st2 = new Student("张三",20); if(st1.equals(st2)) { System.out.println("相等"); }else{ System.out.println("不相等"); } } }; /*class { public static void main(String[] args) { System.out.println("Hello World!"); } }*/
interface PCI { void start(); void stop(); } class NetWrokCard implements PCI { public void start() { System.out.println("Send..."); } public void stop() { System.out.println("stop..."); } }; class SoundCard implements PCI { public void start() { System.out.println("du..."); } public void stop() { System.out.println("sound stop..."); } }; class MainBoard { public void usePCICard(PCI p) { p.start(); p.stop(); } }; class Assembler { public static void main(String[] args) { MainBoard mb = new MainBoard(); NetWrokCard nc = new NetWrokCard(); SoundCard sc = new SoundCard(); mb.usePCICard(nc); mb.usePCICard(sc); //匿名类 /*mb.usePCICard( new PCI() { public void start() { System.out.println("test start..."); } public void stop() { System.out.println("test end..."); } } );*/ //类拟于 class A implements PCI { public void start() { System.out.println("test start..."); } public void stop() { System.out.println("test end..."); } }; mb.usePCICard(new A()); } };