public class Person { private String name; private int age; public Person() { System.out.println("父类"); } public Person(String name, int age) { this.name = name; this.age = age; } public void eat(){} public void play(){} }
public class Student extends Person{ private int studentId; public void study(){} }
public class PersonTest { public static void main(String[] args) { Person person = new Person(); } }
package xingzhuang; public class Rect { private int abscissa; private int ordinate; private int length; private int width; public Rect() { } public Rect(int abscissa, int ordinate, int length, int width) { this.abscissa = abscissa; this.ordinate = ordinate; this.length = length; this.width = width; } public int getAbscissa() { return abscissa; } public void setAbscissa(int abscissa) { this.abscissa = abscissa; } public int getOrdinate() { return ordinate; } public void setOrdinate(int ordinate) { this.ordinate = ordinate; } public int getLength() { return length; } public void setLength(int length) { this.length = length; } public int getWidth() { return width; } public void setWidth(int width) { this.width = width; } public void show () { System.out.println("Rect{" + "abscissa=" + abscissa + ", ordinate=" + ordinate + ", length=" + length + ", width=" + width + '}'); } }
package xingzhuang; public class Circle { private int abscissa; private int ordinate; private int r; public Circle() { } public Circle(int abscissa, int ordinate, int r) { this.abscissa = abscissa; this.ordinate = ordinate; this.r = r; } public int getAbscissa() { return abscissa; } public void setAbscissa(int abscissa) { this.abscissa = abscissa; } public int getOrdinate() { return ordinate; } public void setOrdinate(int ordinate) { this.ordinate = ordinate; } public int getR() { return r; } public void setR(int r) { this.r = r; } public void show() { System.out.println("Circle{" + "abscissa=" + abscissa + ", ordinate=" + ordinate + ", r=" + r + '}'); } }
package xingzhuang; public class Shape { private int abscissa; private int ordinate; public Shape() { } public Shape(int abscissa, int ordinate) { this.abscissa = abscissa; this.ordinate = ordinate; } public int getAbscissa() { return abscissa; } public void setAbscissa(int abscissa) { this.abscissa = abscissa; } public int getOrdinate() { return ordinate; } public void setOrdinate(int ordinate) { this.ordinate = ordinate; } }
package xingzhuang; public abstract class Person { String name; int age; float height; public Person() { } public Person(String name, int age, float height) { this.name = name; this.age = age; this.height = height; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public float getHeight() { return height; } public void setHeight(float height) { this.height = height; } public abstract void say(); }
package xingzhuang; public class Nurse extends Person{ public Nurse() { } public Nurse(String name, int age, float height) { super(name, age, height); } @Override public void say() { System.out.println("hhh"); } public static void main(String[] args) { Nurse n = new Nurse(); n.say(); } } 少了代码的冗余,提高的代码的复用性; 便于功能扩展; 为之后多态性的使用,提供了前提; 5.1.2 继承性的格式 class A extends B{ } A:子类、派生类、subclass; B:父类、超类、基类、superclass; 一旦子类A 继承父类B 以后,子类A 就获取了父类B 中声明的所有属性和方法。特别的,父类中声明为private 的属性或方法,子类继承父类以后,仍然认为获取了父类中私有的结构。只是因为封装性的影响,使得子类不能直接调用父类的结构而已; 子类继承父类之后,还可以声明自己特有的属性或方法:实现功能拓展。子类和父类的关系,不同于子集和集合的关系; Java 只支持单继承和多层继承,不允许多重继承; class SubDemo extends Demo{} // ok class SubDemo extends Demo1,Demo2...{} // error 1 2 5.1.3 继承型的规定 一个类可以被多个子类继承; Java 中类的单继承性:一个类只能有一个父类; 子父类是相对的概念; 子类直接继承的父类,称为:直接父类;间接继承的父类称为:间接父类; 子类继承父类以后,就获取了直接父类以及所有间接父类中声明的属性和方法; 未声明父类的话,继承于Java.lang.Object类; 5.2 方法的重写(override/overwrite) 5.2.1 定义 子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作; 5.2.2 应用 重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,实际执行的是子类重写父类的方法; 5.2.3 规定 声明:<权限修饰符> <返回值类型> <方法名(形参列表)> <throws 异常的类型>{方法体;} 约定俗称:子类中的叫重写的方法,父类中的叫被重写的方法。 子类重写的方法的方法名和形参列表与父类被重写的方法的方法名和形参列表相同; 子类重写的方法的权限修饰符不小于父类被重写的方法的权限修饰符;特殊情况:子类不能重写父类中声明为private 权限的方法; 返回值类型: 父类被重写的方法的返回值类型是void,则子类重写的方法的返回值类型只能是void; 父类被重写的方法的返回值类型是A 类型,则字方法重写的方法的返回值类型可是是A 类或A 类的子类; 父类被重写的方法的返回值类型是基本数据类型(比如double),则子类重写的方法的返回值类型必须是基本数据类型(也必须是double); 子类重写的方法跑出的异常类型不大于父类被重写的方法抛出的异常类型; 子类和父类中的同名同参数的方法要么都声明为非static 的(考虑重写),要么都声明为static 的(不是重写)。 5.3 关键字——Super super 理解为:父类的; super 可以用来调用:属性、方法、构造器 ; super 的使用: 3.1 我们可以在子类的方法或构造器中,通过"super. 属性" 或"super.方法" 的方式,显式的调用父类中声明的属性或方法。但是,通常情况下,我们习惯去省略这个"super."; 3.2 特殊情况:当子类和父类中定义了同名的属性时,我们要想在子类中调用父类中声明的属性,则必须显示的 使用"super. 属性" 的方式,表明调用的是父类中声明的属性; 3.3 特殊情况:当子类重写了父类中的方法后,我们想在子类的方法中调用父类中被重写的方法时,必须显示的使用"super. 方法" 的方式,表明调用的是父类中被重写的方法; super 调用构造器 4.1 我们可以在子类的构造器中显示的使用super( 形参列表)"的方式,调用父类中声明的指定的构造器; 4.2 super( 形参列表)的使用,必须声明在子类构造器的首行! 4.3 我们在类的构造器中,针对于this( 形参列表) 或super( 形参列表)只能二选一,不能同时出现; 4.4 在构造器的首行,既没有显式的声明"this( 形参列表)" 或"super( 形参列表)",则默认的调用的是父类中的空参构造器。super(); 4.5 在类的多个构造器中,至少有一个类的构造器使用了super( 形参列表), 调用父类中的构造器。 5.4 子类对象实例化过程 从结果上看: 子类继承父类以后,就获取了父类中声明的属性或方法。创建子类的对象中,在堆空间中,就会加载所有父类中声明的属性; 从过程上看: 当我们通过子类的构造器创建子类对象时, 我们一定会直接或间接的调用其父类构造器,直到调用了java.lang.Object 类中空参的构造器为止。正因为加载过所有的父类结构,所以才可以看到内存中有父类中的结构,子类对象可以考虑进行调用。 明确: 虽然创建子类对象时,调用了父类的构造器,但自始至终就创建过一个对象,即为new 的子类对象。 5.5 面向对象特征之三——多态性 理解多态性:可以理解为一个事物的多种态性。 何为多态性: 对象的多态性:父类的引用指向子类的对象( 或子类的对象赋值给父类的引用)。 多态的使用:虚拟方法调用 有了对象多态性以后,我们在编译期,只能调用父类声明的方法,但在执行期实际执行的是子类重写父类的方法。简称:编译时,看左边;运行时,看右边; 若编译时类型和运行时类型不一致, 就出现了对象的多态性 (Polymorphism); 多态情况下, “看左边”:看的是父类的引用(父类中不具备子类特有的方法); “看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)。 多态性的使用前提: ① 类的继承关系; ② 方法的重写。