package cn.pen;
/*final 是一个java的关键字,用于修饰局部变量、属性、方法、类,表示最终的意思。
final修饰类表示最终类,无法被继承。public final class Penguin{}
final修饰符方法,方法就不能被重写。所以final修饰的是最终子类或最终类
final 修饰属性,经常和static搭配使用,形成静态常量。静态常量不能被改变
修饰变量final 修饰基本数据类型 ,表示a中的内容(值)不能被改变final int a = 10;
final 修饰引用数据类型,表示person中的内容(地址)不能被概念 final Person person = new Person();*/
//子类 企鹅
public class Penguin extends Pet {
private String gender;
public static final String SEX_MALE = "Q仔";
public static final String SEX_FEMALE = "Q妹";
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Penguin() {
super();
}
public Penguin(String name, int health, int love, String gender) {
super(name, health, love);
this.gender = gender;
}
@Override
public void showInfo() {//方法重写
super.showInfo();
System.out.println(",我是一只" + this.getGender());
}
@Override
public void eat() {//方法实现,完全重写
System.out.println(super.getName() + "在吃鱼...");
super.setHealth(super.getHealth() + 5);
}
public void swimming() {
System.out.println("企鹅在游泳...");
super.setHealth(super.getHealth() - 10);
super.setLove(super.getLove() + 5);
}
}
package cn.pen;
//主人类
public class Master {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Master() {
super();
}
public Master(String name) {
super();
this.name = name;
}
//添加一种动物,就增加一条引用动物代码
/*public void feed(Dog dog) { //把子类Dog引用过来,提取Dog中的属性
System.out.println(this.getName() + "正在喂:" + dog.getName());
dog.eat(); //再把Dog中eat方法引用过来 */
//只需一条引用父类,就可以被所有动物使用
//父类作为方法形参实现多态
/* public void feed(Pet pet) { //把父类Pet引用过来,Dog把自己赋给Pet,
System.out.println(this.getName() + "正在喂:" + pet.getName());
pet.eat(); }
父类作为方法的返回值实现多态:* */
public Pet adoptPet(int type) { //从Test得到type,然后判断
Pet pet = null; //类型转换
if(1 == type) {
pet = new Dog();
}else {
pet = new Penguin();
}
return pet; //得到返回值 ,返回给Test
}
public void play(Pet pet) {
if(pet instanceof Dog) {
Dog dog = (Dog) pet;
dog.catchFlyDisc();
}else if(pet instanceof Penguin) {
Penguin penguin = (Penguin) pet;
penguin.swimming();
}
}
}
package cn.pen;
//子类 狗
public class Dog extends Pet{
private String strain;
public String getStrain() {
return strain;
}
public void setStrain(String strain) {
this.strain = strain;
}
public Dog() {
super();
}
public Dog(String name, int health, int love, String strain) {
super(name, health, love);
this.setStrain(strain);
}
public void showInfo() {
super.showInfo();//在继承的基础上部分重写,完全重写就不需要引入父类方法,自己全部重写
System.out.println(",我是一只" + this.getStrain());
}/*:方法的重写
当子类从父类继承过来的方法不能满足自身需要时,子类可以根据自身情况进行方法重写(overwrite/override)
方法重写建立在继承的基础上,没有继承,就没有重写! 子类根据自身情况,可以选择部分重写和完全重写
重写的规则:1.方法名称相同2. 参数列表相同3. 子类的访问权限一定 >= 父类访问权限 4. 返回值和父类相同或者是其子类
何时使用继承: 符合 is – a 关系;学生 is a 人;老师 is a 人;
继承实现代码重用
当 多个子类拥有共同的属性和行为时,人为把共同的属性和方法提取到父类中,子类继承父类实现代码重用
*/
public void eat() {//方法实现(完全重写)
System.out.println(super.getName() + "吃狗粮...");
super.setHealth(super.getHealth() + 3);
/*实现(implement):子类继承抽象父类时,一定要重写父类的抽象方法,此时父类的抽象方法没有方法体,也即没有实现;
* 子类一定重写父类的抽象方法也即实现了父类的抽象方法。实现是一种特殊的重写。实现建立在重写的继承上。*/
}
//父类没有的方法
public void catchFlyDisc(){
System.out.println("狗狗在玩飞盘...");
super.setHealth(super.getHealth() - 10);
super.setLove(super.getLove() + 6);
}
}
package cn.pen;
//父类:动物
public abstract class Pet {
//abstract(抽象) 抽象类:public abstract class 类名 {}
//抽象类过于抽象,实例化后无语义 => 不能实例化
private String name;
private int health;
private int love;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHealth() {
return health;
}
public void setHealth(int health) {
if(health < 0) {
this.health = 100;
System.out.println("健康值不合法!");
}else {
this.health = health;
}
}
public int getLove() {
return love;
}
public void setLove(int love) {
this.love = love;
}
public Pet() {
this.health = 100;
this.love = 0;
}
public Pet(String name, int health, int love) {
this.name = name;
this.health = health;
this.love = love;
}
public void showInfo() {
System.out.print("我的姓名:"+this.getName());
System.out.print(",健康值:"+this.getHealth());
System.out.print(",亲密度"+this.getLove());
}//吃方法,动物都有吃的行为(方法);但不同的动物吃的方法不同,吃的东西不同,所以吃是个抽象方法
public abstract void eat();
/*因为动物都有睡觉的行为(动物共有的),但是不同的动物 睡觉方法不同,比如:
* 人继承于动物,鱼继承于动物。人有睡觉(闭眼睡)的方法,鱼有睡觉的方法,动物也有睡觉的方法
* 虽然都是睡觉,但是睡觉方法却不同,所以说睡觉这个方法不能再父类实习,只有在具体到子类时才能实现
* 此时可以把该方法定义成抽象方法。抽象方法却只能存在于抽象类,所以有抽象方法的类称为抽象类(abstract class)
* 所以:如果一个方法过于抽象无法实现,需要把该方法声明为抽象方法。形式:public abstract void eat();
* 注意:抽象方法一定位于抽象类中。
抽象方法没有方法体。
抽象类中的方法不一定都是抽象方法。
子类继承抽象类,一定要根据自身情况重写抽象类的抽象方法,除非子类也是抽象类。
* */
}
package cn.pen;
//执行类
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
//Dog dog = new Dog("二狗",90,0,"土狗"); //把Dog的类引入进来
//Master master = new Master("王二小"); //在把主人类引用进来
//master.feed(dog); //把dog(Dog类的入口或钥匙)引入主人类的feed方法
//dog.showInfo(); //引出Dog类的showInfo方法
/*执行结果:
* 王二小正在喂:二狗
二狗吃狗粮...
我的姓名:二狗,健康值:93,亲密度0,我是一只土狗*/
//每个动物都有吃,但吃的方法不同,造成的结果也就不同,但动物有很多种,我们不能每个动物子类都这样写一遍
//所以我们用到了:多态
/*多态
*
*
软件设计原则—开闭原则 ,对拓展开放,对修改关闭。为什么要使用多态?对系统进行业务拓展,增加系统的可维护性。
可以理解为多种状态/多种形态
同一事物,由于条件不同,产生的结果不同
程序中的多态
同一引用类型,使用不同的实例而执行结果不同的。
同:同一个类型,一般指父类。
不同:不同的子类实例
不同:针对同一方法执行的结果不同
比如说睡觉,不同的动物睡觉方法不同,最后结果不同*/
/*在多态中存在两种类型转换,一种是自动类型转换,一种是强制类型转换。
在引用数据类型转换过程中,
自动类型转换也称向上类型转换。子类可以自动转换成父类。
多态的实现形式
* 父类类型 引用 子类对象(本质)
Pet pet=null; //同一引用类型(父类)
pet = new Dog("二狗",90,0,"土狗") ;// [ 自动类型转换] 父类类型引用子类对象,当调用eat方法时,执行的是被子类对象重写/实现的eat方法。
pet.eat(); // 呈现多态
结果:二狗吃狗粮...
王二小正在喂:二狗
*
*/
//父类作为方法形参实现多态
/*Pet pet=null; //同一引用类型(父类)
pet=new Dog("二狗",100,0,"土狗"); // 父类引用 引用 子类对象
Master master = new Master("王二小");
master.feed(pet); // 呈现多态
pet.showInfo(); // 呈现多态
pet=new Penguin("大脚", 90, 50, Penguin.SEX_FEMALE); // 父类引用 引用 子类对象
master.feed(pet); // 父类引用 引用 子类对象
pet.showInfo(); // 呈现多态
同样的结果,但是我们只在主人类那只需写引用父类的代码就可以了 ,无需向上面那样每个动物都需在主人类那写一遍
* 现在没增加一种动物就只会多写一个类就可以了,无需再主人类那加一条方法;实现一个方法多种使用
结果:
王二小正在喂:二狗
二狗吃狗粮...
我的姓名:二狗,健康值:103,亲密度0,我是一只土狗
王二小正在喂:大脚
大脚在吃鱼...
我的姓名:大脚,健康值:95,亲密度50,我是一只Q妹
父类作为方法的返回值实现多态:
*/
System.out.println("欢迎光临sxt宠物店");
System.out.println("请选择领养的宠物 1.狗狗 2.企鹅 ");
Scanner arr=new Scanner(System.in);
int type=arr.nextInt(); //控台输入type
Master master = new Master("王二小"); //引用Master类
Pet pet = master.adoptPet(type); //把type赋值给Master类adoptPet方法判断,得出来结果后赋给pet
/*强制类型转换也称向下类型转换。父类可以强制转换成子类
* 子类类型 引用 = (子类)父类对象
* 一般而言,需要判断父类对象的真实类型,用instanceof关键字
* obj instanceOf 类/接口 判断obj是否是类/接口的实例
instanceof通常和强制类型转换结合使用
instanceof是判断是否能强制转换,能返回true
* 如果要调用子类特有的方法时,一定要强制类型转换,通过instanceof鉴别具体类型*/
if(pet instanceof Dog) { //得到从Master得到的返回值pet,然后判断是强制转换给Dog还是Penguin,
Dog dog = (Dog) pet; //判断完之后再一个一个赋值
dog.setName("二狗");
dog.setHealth(90);
dog.setLove(20);
dog.setStrain("土狗");
}else if(pet instanceof Penguin) {
Penguin penguin = (Penguin) pet;
penguin.setName("大脚");
penguin.setHealth(90);
penguin.setLove(20);
penguin.setGender(Penguin.SEX_FEMALE);
}
master.play(pet); //再把被赋完值之后的pet引入Master的piay方法执行再返回结果
pet.showInfo();
}
}