day15
class Animal{ //属性 String name; int age; String color; //方法:显示信息 public void show(){ System.out.println("名字:"+name+" 年龄:"+age+" 颜色:"+color); } } //编写狗的子类继承动物父类 class Dog extends Animal{ //编写子类中独有属性和方法 String strain;、 //重写也叫做覆盖override:在子类中重写父类的方法,必须与父类的方法名称一致,参数列表一致、返回类型一致、修饰符一致 public void show(){ //在子类可以直接访问父类中的属性(前提:父类中属性没有使用private修饰) System.out.println("名字:"+name+" 年龄:"+age+" 颜色:"+color+" 品种:"+strain); } } //等价于 /*class Dog extends object{ }*/ class Cat extends Animal{ //独有属性:性别 char sex; }
1.重写
----子类方法名称必须与父类方法名称一致
---参数列表一致
---返回类型一致或父类方法返回类型的子类类型
---修饰符不能缩小范围
子类不能重写:
---构造方法不能重写
---属性不能重写
---静态方法不能重写
---私有方法不能重写
//编写测试类 class Test{ public static void main(String[] args){ //创建狗的对象 Dog d=new Dog(); //显示信息 d.show();//先在Dog类中找show方法,如果没有找到则再去父类中找 } }
2.this与super关键字访问实例变量区别
this 关键字---代表当前这个对象
---this可以访问本类中的实例变量,实例方法也可以访问本类中
的其他构造方法
---this还可以访问父类中的实例变量
super关键字---表示超类
---super只能在子类中使用,可以访问父类中的实例变量
注意:--如果访问实例变量时,默认前面添加this,但是使用this.访问实例变量时
先在当前类中找该属性
--使用super直接去父类中找该属性或方法
--使用super访问父类的构造方法
class Student extends Person{ //无参构造 public Student(){ } public Student(String name,char sex,int age,int id){ super(name,sex,age);//父类构造了此方法,直接调用 this.id=id; } }
3.当实例化子类时父类做了什么?
--先执行父类的构造方法,然后再执行子类的相匹配构造方法
---如果子类构造方法中没有指名则默认调用父类的无参构造方法;
---如果子类构造方法中指明调用父类哪个构造方法,则先执行父类
相匹配的构造方法,然后再执行子类相匹配构造方法。
建议:--当手动编写构造方法时,先编写无参构造方法,再编写
所需要的构造方法。
/* 某个汽车租赁公司有多种紫车可以出租,计算汽车的租金 Vehicle是所有车的父类,属性:品牌,车牌号 方法:返回总租金的方法:public double getSumRent(int days){} Car:小汽车类是Vehicle的子类,属性:车型(两厢,三厢,越野) 两厢:每天300,三厢:每天350,越野:每天500 Bus:多座汽车,属性:座位数 座位数<=16:每天400 座位数>16:每天600 测试类: 根据用户选择不同,计算总租金并输出总租金 */ class Vehicle{ //属性 String brand; String id; //构造方法 public Vehicle(){ } public Vehicle(String brand,String id){ this.id=id; thid.brand=brand; } //方法:返回总租金的方法 public double getSumRent(int days){ return 0; } } //编写小轿车子类继承车的父类 class Car extends Vehicle{ //编写独有属性 String type; //构造方法 public Car(){ super(); this.type="三厢"; } public Car(String brand,String is,String type){ super(brand,id); this.type; } //重写父类的总租金方法 public double getSumRent(int days){ //判断,根据车型获取日租金 switch(this.type){//注意:当type属性没有赋值时,该值为null,在java中,switch表达式中如果为null,就会出现空指针异常 case "两厢": return 300 * days; case "三厢": return 350 * days; default: return 500 * days; } } } //编写小轿车测试类 class CarTest{ public static void main(String[] args){ //实例化小轿车 Car c=new Car(); System.out.println("总租金:"+c.getSumRent(3)); } }
4.多态:
---多态语法格式:
--父类类名 引用名称=new 子类类名();
--当是多态时,该引用名称只能访问父类中的属性和方法,
但是优先访问子类重写以后的方法;
---多态:将多个对象调用一个方法,得到不同的结果;
---满足多态的条件:
--子类必须继承父类;
--子类重写父类的方法;
--父类类名 引用名称=new 子类类名();
class Test{ /* 多态的语法格式: 父类类名 引用名称=new 子类类名(); 注意:当是多态时,该引用名称只能访问父类中的属性和方法啊,但是优先访问子类重写以后的方法 */ Vehicle c=new Car(); System.out.println(c.brand);//null System.out.println(c.id);null //System.out.println(c.type);//出现编译错误,因为引用名称c是父类类型,因此只能访问父类中的属性 c.print();//ok,在父类中定义了此方法 System.out.println(c.getSumRent(1)); }
5.多态的好处:减少代码的冗余性
6.为什么要进行类型的转换:
---多态中的两种类型转换
--向上转型:也叫做自动类型转换
父类类型 引用名称=new 子类类名();
--向下转型:也叫做强制类型转换
当是多态时,并且访问子类独有的属性或方法,则必须进行
向下转型
实例:
class Pet{ //方法 public void eat(){ System.out.println("宠物正在吃东西....."); } } //编写狗的子类继承宠物父类 class Dog extends Pet{ //重写父类的eat方法 public void eat(){ System.out.println("狗正在吃狗粮...."); } //编写独有的方法:玩飞盘 public void play(){ System.out.println("狗正在玩飞盘...."); } } //编写猫的子类继承宠物父类 class Cat extends Pet{ //重写父类的吃的方法 public void eat{ System.out.println("猫正在吃猫粮...."); } //编写独有的方法:抓老鼠 public void catching(){ System.out.println("猫正在抓老鼠...."); } } //编写主人类 class Master{ //方法:喂养狗 /*public void feed(Dog dog){ dog.eat(); } public void feed(Cat cat){ cat.eat(); }*/ /* 总结得到:以上喂养猫和狗都属于宠物,因此能否编写主人喂养宠物方法 */ public void feed(Pet pet){//Pet pet=new Dog(); Pet pet=new Cat() pet.eat(); } } //测试类 class Test{ public static void main(String[] args){ //创建主人对象 Master m=new Master(); //创建狗对象 Dog d=new Dog(); //主人喂养宠物 m.feed(d); m.feed(new Cat()); } } class Test2{ public static void main(String[] args){ Pet p=new Dog();//构成多态;也就是说向上转型 /*p.eat(); //p.play();// 出现编译错误,父类类型不能访问子类独有属性或方法 //解决办法:进行向下转型 Dog d=(Dog)p; //此时就可以使用引用名称d访问狗中的play方法 d.play(); */ /*Cat c=(Cat)p;//出现运行错误,原因:当前引用名称p存放的是狗对象的地址,因此不能强制转换为猫 c.catching();*/ //解决办法:当进行向下转型时,建议先进行判断,当合法则在转为对应的类型,则使用instanceof关键字 p=new Cat(); if(p instanceof Dog){ Dog dog=(Dog)p; dog.play(); }else if(p instanceof Cat){ Cat cat=(Cat)p; cat.catching(); } } }