类的继承和多态
继承
基础概念
概念:
- 子类拥有父类的所有属性和方案,属性和方法的修饰符不能是private
- 私有属性和方法一样会继承,但是不能对其访问
优点:
- 代码复用
- 为多态做铺垫
JAVA特点: JAVA的类的继承是单继承(一个类只有一个直接父类)
形式
class 子类名 extends 父类名
操作
方法的重写
含义:
子类可以重新修改从父类继承的方法,当子类调用该方法时候,系统优先调用重写的
语法规则:
返回值类型,方法名,参数类型及个数,要与父类继承的方法相同
注意:系统会自动继承Object类
重写Object类:
直接打印类名称,会自动加上.tostring
方法。
编译器技巧:快读构建父类方法
方法声明的形式:访问权限,返回值类型,方法名称(参数列表)抛出异常
方法重写的规则:两同,两小,一大
两同: 法名相同,形参列表相同
两小:
- 子类方法的返回值类型<=父类方法返回值类型
- 子类方法声明抛出的异常类<=父类方法声明抛出的的异常类
一大: 类方法的访问权限>=父类方法的访问权限
注意: 覆盖的方法和被覆盖的方法只能都是类方法/实例方法。不能既有类方法,又有实例方法
构造方法的继承
创建对象时候:先创建父类对象,再创建子类构造方法:
先执行父类构造方法,再执行子类构造方法。
默认为无参构造方法super()
<这条语句必须为子类构造方法的第一句>
public class Father {
int a;
public Father(int a)
{
this.a=a;
}
}
public class Child extends Father {
super();//会报错
/*
正确做法
public Child(int a) {
super(a);
}
*/
}
-
一个类中,先执行属性初始化,在执行构造方法初始化,
-
先父类,再子类
-
子类属性与父类属性重名,子类对象优先调用子类的属性,方法也是
-
父类和子类有重名的属性时候,在子类对象中拥有他们各自的内存空间和属性值
关键字
instanceof
作用:
判断某对象是否是某类的一个实例
要求:
instanceof前面对象和后面类必须是父类和子类关系(否则编译错误)
用法及常识:
public class Child extends Father {
public static void main(String[] args) {
Father f=new Father();
Father fc=new Child();
Child c=new Child();
System.out.println(f instanceof Father);
//判断父类对象的否的父类类型的一个实例 : true
System.out.println(f instanceof Child);//false
System.out.println(c instanceof Father);//true
System.out.println(c instanceof Child);//true
//下面是上转型对象
System.out.println(fc instanceof Child);//true
System.out.println(fc instanceof Father);//true
}
final
作用:
- 修饰的类不能被继承,成为最终类;
-
- 如果被继承,在子类处编译错误
public fianl Father{}
- 修饰方法不能被重写
-
- 如果被重写,在final方法处编译错误
overwrite
作用:
super
限定父类成分
子类中的属性/方法与父类重名,使用父类的,使用super限定
public class Child extends Father {
int a=20;
public Child(int a) {
super(a);
// TODO Auto-generated constructor stub
}
public void m1()
{
System.out.println("Child m1----");
}
public void m2()
{
System.out.println(a);
m1();
System.out.println(super.a);
super.m1();
}
public static void main(String[] args) {
Child c=new Child(1);
c.m2();
}
}
/*
输出结果
20
Child m1----
1
Father m1----
*/
引用父类的构造方法
super必须在子类该构造方法的第一条语句
用法:
如果父类是有参构造方法,在子类中:super(参数)
实例:
父类:
public class Product {
String id;
String name;
double count;
/*public Product()
{
super();
}*/
public Product(String a, String b, Double c) {
id = a;
name = b;
count = c;
}
子类:(会报错)
package prj4;
public class Phone extends Product{
int size;
public Phone(String id,String name ,double price,int size)
{
// super(name, id, null);
this.id=id;
this.name=name;
this.count=price;
this.size=size;
}
}
原因:
子类带参数构造方法时:会自动加入super()
而父类没有的无参构造方法,
所以报错
portected
同一个包下,是可以访问受保护的方法/变量
不同包下,不能访问,受保护的属性和方法,
不同包下的,子类可以受保护的变量和方法
上转型对象
用子类创建一个对象,
并把这个对象的引用放到父类类声明的变量中
形式: 父类名 变量名=new 子类名
当子类重写父类的方法时,用上转型方法
还原上转型对象
形式子类名 新变量名 = (子类名)上转型对象名
注意:
其他类 新变量名 = (其他类名)上转型变量名
编译不报错,但是执行有问题
注意:下面三个都是上转型变量,但是并不相同
public class Test {
public static void main(String[] args) {
Fathter a=new Child();
//a 能调用Father的所有方法
Shape1 aa=new Child();
//aa 能调用Shape1的所有方法
Interface1 aaa=new Child();
//aaa 能调用Interface1的所有方法
}
}
内涵
package sdut.W;
public class Test {
public static void main(String[] args) {
AA aa=new AA();
System.out.println(aa.a);
System.out.println(aa.b);
aa.m1();
aa.m2();
System.out.println("=================================");
BB bb=new BB();
System.out.println(bb.a);
System.out.println(bb.b);
System.out.println(bb.c);
bb.m1();
bb.m2();
bb.m3();
System.out.println("=================================");
AA ab=new BB();
System.out.println(ab.a);
System.out.println(ab.b);//父类的属性
//编译错误 System.out.println(ab.c);
ab.m1();
ab.m2();//子类的方法
//编译错误 ab.m3();
//编译错误 BB ba=new AA();
}
}
多态
概念
概念0.1: 定义了一个Father类型的F,它先指向ChildOne对象实例,后指向ChildTwo对象实例,再指向...
概念0.2: 在同一个继承结构中,使用相同逻辑的代码,处理不同的对象,从而达到执行不同的行为。
概念1.1: 只有在运行的时候才会知道引用变量所指向的具体实例对象。
概念1.2: 程序中定义的引用变量所指向的“ 具体类型和通过该引用变量发出的方法调用 ” 在编程时并不确定,而是在程序运行期间才确定。
概念1.3: 一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
概念2.1: 不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上。
(从而导致该引用调用的具体方法随之改变)
概念2.2: 不修改程序代码,就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态。
条件
继承、重写、向上转型
Shape shape;
//shape =new shape();
shape=new Triangle(3, 4, 5);//上转型对象
System.out.println(shape.length());
System.out.println(shape.area());
shape=new Y(10);//上转型对象
System.out.println(shape.length());
System.out.println(shape.area());
shape =new C(5, 4);//上转型对象
System.out.println(shape.length());//多态
System.out.println(shape.area());