Java07-接口与继承

it2024-12-28  8

https://www.nowcoder.com/tutorial/94/ae05554a3ad84e42b6f9fc4d52859dc4

https://how2j.cn/k/interface-inheritance/interface-inheritance-interface/289.html

目录

1 接口物理攻击接口继承英雄,实现物理攻击接口魔法攻击接口继承英雄,实现魔法攻击接口实现物理、魔法攻击接口练习 2 对象转型2.1 引用类型、对象类型2.2 子类转父类2.3 父类转子类2.4 其他2.5 instanceof2.6 练习 3 重写 = 覆盖父类 Item子类 LifePotion练习 4 多态4.1 操作符的多态4.2 类的多态4.3 三要素4.4 好处4.5 练习 5 隐藏5.1 父类 类方法5.2 隐藏5.3 练习 6 super6.1 子类调用父类带参构造方法6.2 调用父类属性6.3 调用父类方法 7 Object类7.1 toString()7.2 finalize()7.3 equals(),==7.4 其他7.5 练习 8 final9 抽象类9.1 简单例子9.2 注意9.3 与接口的区别9.4 练习 10 内部类10.1 非静态内部类10.2 静态内部类10.3 匿名类10.3.1 使用外部局部变量 10.4 本地类10.5 练习 11 默认方法11.1 练习 12 综合练习AnimalPetSpiderCatFish测试

1 接口

物理攻击接口

package11个程序_接口与继承.a1接口.s1_物理攻击接口; public interface AD { public void physicAttack(); }

继承英雄,实现物理攻击接口

设计英雄,能物理攻击 类:ADHero 继承 Hero 类,继承了 name, hp, armor 等属性

Hero:

package11个程序_接口与继承.a1接口.s1_物理攻击接口; public class Hero { String name; float hp; //血量 float armor; //护甲 int moveSprrd; //速度 public static void main(String[] args) { // 创建1个对象 new Hero(); // 引用h 指向这个对象 Hero h = new Hero(); } } package11个程序_接口与继承.a1接口.s1_物理攻击接口; public class ADHero extends Hero implements AD{ @Override public void physicAttack() { System.out.println("警醒物理攻击!"); } }

魔法攻击接口

package11个程序_接口与继承.a1接口.s1_物理攻击接口; public interface AP { public void magicAttack(); }

继承英雄,实现魔法攻击接口

package11个程序_接口与继承.a1接口.s1_物理攻击接口; public class APHero extends Hero implements AP{ @Override public void magicAttack() { System.out.println("进行魔法攻击!"); } }

实现物理、魔法攻击接口

package11个程序_接口与继承.a1接口.s1_物理攻击接口; public class ADAPHero extends Hero implements AD,AP { @Override public void physicAttack() { System.out.println("进行物理攻击!"); } @Override public void magicAttack() { System.out.println("进行魔法攻击!"); } }

练习

治疗者接口:Healer 方法: heal() 设计 Support 类 - 辅助英雄,继承 Hero,实现接口 Healer

package11个程序_接口与继承.a1接口.练习; public interface Healer { public void heal(); } package11个程序_接口与继承.a1接口.练习; public class Support extends Hero implements Healer{ @Override public void heal() { System.out.println("治疗"); } }

2 对象转型

2.1 引用类型、对象类型

可一致,可不一致

一致: ADHero ad = new ADHero(); new ADHero() 是对象 ad 是引用 类型都是 ADHero

2.2 子类转父类

不一致: Hero h = new ADHero();

Hero h = new Hero(); ADHero ad = new ADHero(); h = ad;

ADHero 是继承 Hero 可以说 ADHero 可当成 Hero 来用(子类转父类) 反之,Hero 不可当成 ADHero 来用!

2.3 父类转子类

2 种情况:转换成功、转换失败

成功案例:

Hero h =new Hero(); ADHero ad = new ADHero(); h = ad; ad = (ADHero) h;

2 个失败案例:

Hero h =new Hero(); ADHero ad = new ADHero(); Support s =new Support(); h = s; ad = (ADHero)h; Hero h = new Hero(); ADHero ad = new ADHero(); ad = (ADHero)h;

2.4 其他

实现类可以转接口(反之不行!):

ADHero ad = new ADHero(); AD adi = ad;

没有继承关系的两个类,相互转换 一定失败!

2.5 instanceof

instanceof Hero 判断引用 是否是 Hero 类型,或 Hero 子类

//判断引用h1指向的对象,是否是ADHero类型 System.out.println(h1 instanceof ADHero);

2.6 练习

找错误:

package charactor; public class Hero { public String name; protected float hp; public static void main(String[] args) { ADHero ad = new ADHero(); Hero h = ad; AD adi = (AD) h; APHero ap = (APHero) adi; } } Hero h = ad; 这行没错 子转父 AD adi = (AD) h; h指向ADHero,强转 AD 也行 APHero ap = (APHero) adi; adi 指向 AD,不能强行转 APhero,所以这里有问题

3 重写 = 覆盖

子类继承父类,实现同一个方法,就是 重写=覆盖(override)

父类 Item

package11个程序_接口与继承.a3_重写覆盖; public class Item { String name; int price; public void buy(){ System.out.println("购买"); } public void effect(){ System.out.println("物品使用后,有效果!"); } }

子类 LifePotion

package11个程序_接口与继承.a3_重写覆盖; public class LifePotion extends Item{ public void effect(){ System.out.println("药品使用后,可以回血!"); } } public static void main(String[] args) { Item item = new Item(); item.effect(); LifePotion lifePotion = new LifePotion(); lifePotion.effect(); }

练习

设计类 MagicPotion 蓝瓶,继承Item, 重写 effect 方法 输出 “蓝瓶使用后,可以回魔法”

package11个程序_接口与继承.a3_重写覆盖; public class MagicPotion extends Item{ public void effect(){ System.out.println("蓝瓶使用后,可以回魔法!"); } } MagicPotion magicPotion = new MagicPotion(); magicPotion.effect();

4 多态

2 种: 操作符的多态 类的多态

4.1 操作符的多态

int k = i+j; //如果+号两侧都是整型,那么+代表 数字相加 String c = a+b; //如果+号两侧,任意一个是字符串,那么+代表字符串连接

4.2 类的多态

package11个程序_接口与继承.a4_多态.类的多态; public class Item { String name; int price; public void buy(){ System.out.println("购买"); } public void effect(){ System.out.println("物品使用后,有效果!"); } public static void main(String[] args) { Item item = new Item(); Item lifePotion = new LifePotion(); Item magicPotion = new MagicPotion(); item.effect(); lifePotion.effect(); magicPotion.effect(); } }

4.3 三要素

继承 重写 父类引用指向子类对象

4.4 好处

可替换 可扩充 接口性 灵活 - 提高效率 简化

4.5 练习

1 设计接口 Mortal,有方法 die 2 实现接口 ADHero,APHero,ADAPHero 这 3 类,实现 Mortal 接口 不同类实现 die方法,打印出不同字符串 3 Hero 类添加方法,调用 m.die方法 public void kill(Mortal m) 4 在主方法中 实例化 Hero对象:盖伦 实例化 3 对象,分别是ADHero,APHero,ADAPHero 实例 让盖伦 kill 这3对象

1 设计接口 Mortal,有方法 die

package11个程序_接口与继承.a4_多态.练习; public interface Mortal { public void die(); }

2 ADHero,APHero,ADAPHero 这 3 类,实现 Mortal 接口 不同类实现 die方法,打印出不同字符串 3 Hero 类添加方法,调用 m.die方法 public void kill(Mortal m)

public void kill(Mortal m){ m.die(); }

4 在主方法中操作:

package11个程序_接口与继承.a4_多态.练习; public class Hero { String name; float hp; //血量 float armor; //护甲 int moveSprrd; //速度 public void kill(Mortal m){ m.die(); } public static void main(String[] args) { Hero h = new Hero(); h.name = "盖伦"; Mortal m1 = new ADHero(); Mortal m2 = new APHero(); Mortal m3 = new ADAPHero(); h.kill(m1); h.kill(m2); h.kill(m3); } }

5 隐藏

重写:子类覆盖父类的 对象方法 隐藏:子类覆盖父类的 类方法

5.1 父类 类方法

public class Hero { public String name; protected float hp; //类方法,静态方法 //通过类就可以直接调用,类方法 public static void battleWin(){ System.out.println("hero battle win"); } }

5.2 隐藏

public class ADHero extends Hero implements AD{ @Override public void physicAttack() { System.out.println("进行物理攻击"); } //隐藏父类的battleWin方法 public static void battleWin(){ System.out.println("ad hero battle win"); } public static void main(String[] args) { Hero.battleWin(); ADHero.battleWin(); } }

5.3 练习

Hero h =new ADHero(); h.battleWin(); /*battleWin 是类方法 h是父类类型的引用 但是指向一个子类对象*/ h.battleWin(); 会调用父类的方法、子类的方法? Hero中的方法是静态的,不可以被重写 所以会打印父类中的方法 把static去掉,则打印子类中重写的方法

6 super

this()、super() 必须是构造函数中的第1条语句!

构造函数: public 类名(类型 参数){}

普通函数: public 返回类型 函数名(类型 参数){} 区别就是 有无返回类型

1 LifePotion、MagicPotion

package11个程序_接口与继承.a5_super; public class LifePotion extends Item { public void effect(){ System.out.println("药品使用后,可以回血!"); } } package11个程序_接口与继承.a5_super; public class MagicPotion extends Item { public void effect(){ System.out.println("蓝瓶使用后,可以回魔法!"); } }

2 Hero

package11个程序_接口与继承.a5_super; public class Hero { String name; //姓名 float hp; //血量 float armor; //护甲 int moveSpeed; //移动速度 public void useItem(Item i){ System.out.println("hero use item"); i.effect(); } public Hero(){ System.out.println("Hero的构造方法 "); } public static void main(String[] args) { new Hero(); } }

3 ADHero

package11个程序_接口与继承.a5_super; public interface AD { public void physicAttack(); } package11个程序_接口与继承.a5_super; public class ADHero extends Hero implements AD { @Override public void physicAttack() { System.out.println("进行物理攻击!"); } public ADHero(){ System.out.println("AD Hero 构造方法"); } public static void main(String[] args) { new ADHero(); } }

4 Hero

package11个程序_接口与继承.a5_super; public class Hero { String name; //姓名 float hp; //血量 float armor; //护甲 int moveSpeed; //移动速度 public void useItem(Item i){ System.out.println("hero use item"); i.effect(); } public Hero(){ System.out.println("Hero的无参构造方法 "); } public Hero(String string){ System.out.println("Hero 有1个参数的构造方法"); } public static void main(String[] args) { new Hero(); } }

6.1 子类调用父类带参构造方法

5 ADHero

package11个程序_接口与继承.a5_super; public class ADHero extends Hero implements AD { @Override public void physicAttack() { System.out.println("进行物理攻击!"); } public ADHero(String name){ super(name); System.out.println("AD Hero 构造方法"); } public static void main(String[] args) { new ADHero("德莱文"); } }

6.2 调用父类属性

super 调用父类 moveSpeed 属性 ADHero 提供属性 moveSpeed

package11个程序_接口与继承.a5_super; public class ADHero extends Hero implements AD { int moveSpeed = 400; @Override public void physicAttack() { System.out.println("进行物理攻击!"); } public ADHero(String name){ super(name); System.out.println("AD Hero 构造方法"); } public int getMoveSpeed(){ return this.moveSpeed; } public int getMoveSpeed2(){ return super.moveSpeed; } public static void main(String[] args) { ADHero adHero = new ADHero("德莱文"); System.out.println(adHero.getMoveSpeed()); System.out.println(adHero.getMoveSpeed2()); } }

6.3 调用父类方法

ADHero 重写 useItem 方法, 在 useItem 中通过 super 调用父类的 useItem 方法

package11个程序_接口与继承.a5_super; public class ADHero extends Hero implements AD { int moveSpeed = 400; @Override public void physicAttack() { System.out.println("进行物理攻击!"); } public ADHero(String name){ super(name); System.out.println("AD Hero 构造方法"); } public int getMoveSpeed(){ return this.moveSpeed; } public int getMoveSpeed2(){ return super.moveSpeed; } public void useItem(Item item){ System.out.println("ADHero use item"); super.useItem(item); } public static void main(String[] args) { ADHero adHero = new ADHero("德莱文"); Item item = new Item(); adHero.useItem(item); // System.out.println(adHero.getMoveSpeed()); // System.out.println(adHero.getMoveSpeed2()); } }

7 Object类

Object 类是所有类的父类

任何类默认继承 Object public class Hero 等价于 public class Hero extends Object

7.1 toString()

Object 类有 toString 方法,→ 所有的类都有 toString 方法 toString():返回当前对象的字符串表达

7.2 finalize()

对象没有任何引用指向时,满足垃圾回收的条件 finalize() 方法会被调用

7.3 equals(),==

equals():

Hero h1= new Hero(); Hero h2= new Hero(); h1.equals(h2);

==: 不是 Object 方法, 可用于判断 两个引用,是否指向同一个对象

7.4 其他

hashCode:返回一个对象的哈希值 线程同步:wait()、notify()、notifyAll() getClass():返回对象的类对象

7.5 练习

重写 Item的 toString(),finalize(),equals() 方法 toString() 返回 Item 的 name + price finalize() 输出当前对象正在被回收 equals(Object o) 首先判断 o 是否是 Item 类型 然后比较两个 Item 的 price 是否相同

package11个程序_接口与继承.a6_Object.练习; public class Item extends Object{ String name; int price; @Override public String toString() { return this.name; } @Override protected void finalize() throws Throwable { System.out.println(this.getClass() + "正在回收..."); } @Override public boolean equals(Object obj) { if(obj instanceof Item){ Item item = (Item) obj; return this.price == item.price; }else { return false; } } public static void main(String[] args) throws Throwable { Item item1 = new Item(); Item item2 = new Item(); item1.price = 100; item2.price = 100; System.out.println("item2.equals(item2) = " + item2.equals(item2)); System.out.println(item1.toString()); item1.finalize(); } }

8 final

修饰 类: public final class Hero{} 该类不能被继承

修饰 方法: public final void useItem(Item i){} 该方法不能被重写

修饰 基本变量: final int hp; 该变量室友一次赋值机会,赋值后不能再赋值

修饰 引用: final Hero h; 该引用只有1次指向对象的机会 指向后,不能更新指向

修饰 常量: public static final int itemTotalNumber = 6;

9 抽象类

类中声明一个方法,这个方法没有实现体,是“空”方法 用 abstract 修饰

9.1 简单例子

1 Hero:

package11个程序_接口与继承.a7_抽象类.s1_简单例子; public abstract class Hero { String name; float hp; float armor; int moveSpeed; public static void main(String[] args) { } public abstract void attack(); }

2 ADHero :

package11个程序_接口与继承.a7_抽象类.s1_简单例子; public interface AD { public void physicAttack(); } package11个程序_接口与继承.a7_抽象类.s1_简单例子; public class ADHero extends Hero implements AD{ @Override public void physicAttack() { System.out.println("进行物理攻击!"); } @Override public void attack() { physicAttack(); } }

3 APHero:

package11个程序_接口与继承.a7_抽象类.s1_简单例子; public interface AP { public void magicAttack(); } package11个程序_接口与继承.a7_抽象类.s1_简单例子; public class APHero extends Hero implements AP{ @Override public void magicAttack() { System.out.println("进行魔法攻击!"); } @Override public void attack() { magicAttack(); } }

4 ADAPHero:

package11个程序_接口与继承.a7_抽象类.s1_简单例子; public class ADAPHero extends Hero implements AD, AP{ @Override public void physicAttack() { System.out.println("既能物理攻击,也能魔法攻击!"); } @Override public void magicAttack() { System.out.println("进行魔法攻击!"); } @Override public void attack() { System.out.println("进行物理攻击!"); } }

9.2 注意

类被声明为抽象类,就不能够被直接实例化 错误例子:

package charactor; public abstract class Hero { public static void main(String[] args) { Hero h= new Hero(); // 错误! 抽象类不能实例化! } }

9.3 与接口的区别

1 子类只能继承1个抽象类,不能继承多个 子类可以实现多个接口

2 抽象类可定义 public, protected, package, private 静态、非静态属性 final、非final属性

接口中声明的属性,只能是 public 静态 final

3 抽象类、接口都可以有实体方法 接口中的实体方法,叫做默认方法

9.4 练习

Item 类设计抽象方法 public abstract boolean disposable() 不同子类,实现 disposable 后,返回不同值

比如 LifePotion 返回 true Weapon, Armor 返回 false

1 Item:

package11个程序_接口与继承.a7_抽象类.练习; public abstract class Item { String xueping; String wuqi; public abstract boolean disposable(); public static void main(String[] args) { System.out.println(); } }

2 LifePotion:

package11个程序_接口与继承.a7_抽象类.练习; public class LifePotion extends Item{ @Override public boolean disposable() { super.xueping = "已使用血瓶"; return true; } public static void main(String[] args) { LifePotion lifePotion = new LifePotion(); System.out.println(lifePotion.disposable() + lifePotion.xueping); } }

3 Weapon:

package11个程序_接口与继承.a7_抽象类.练习; public class Weapon extends Item{ @Override public boolean disposable() { super.wuqi = "子弹已耗尽!"; return false; } public static void main(String[] args) { Weapon weapon = new Weapon(); System.out.println(weapon.disposable() + weapon.wuqi); } }

10 内部类

有为4种: 非静态内部类 静态内部类 匿名类 本地类

10.1 非静态内部类

package11个程序_接口与继承.a8_内部类.s1_简单例子; public class Hero { private String name; float hp; float armor; int moveSpeed; class BattleScore{ int kill; int die; int assit; public void legendary(){ if(kill > 8) System.out.println(name + "超神!"); else System.out.println(name + "尚未超神!"); } } public static void main(String[] args) { Hero hero = new Hero(); hero.name = "盖伦"; BattleScore score = hero.new BattleScore(); score.kill = 9; score.legendary(); } }

10.2 静态内部类

静态内部类 不能直接访问外部类的对象属性

package11个程序_接口与继承.a8_内部类.s2_静态内部类; public class Hero { public String name; protected float hp; public static void battleWin() { System.out.println("battle win!"); } static class EnemyCrystal{ int hp = 500; public void checkIfVictory(){ if(hp == 0){ Hero.battleWin(); //静态内部类不能直接访问外部类的对象属性 // System.out.println(name + " win this game"); 错误! } } } public static void main(String[] args) { Hero.EnemyCrystal crystal = new Hero.EnemyCrystal(); crystal.checkIfVictory(); } }

10.3 匿名类

匿名类:声明一个类的同时,实例化它

package11个程序_接口与继承.a8_内部类.s3_匿名类; public interface AD { public void physicAttack(); } package11个程序_接口与继承.a8_内部类.s3_匿名类; public class ADHero extends Hero implements AD { @Override public void physicAttack() { System.out.println("进行物理攻击!"); } @Override public void attack() { physicAttack(); } } package11个程序_接口与继承.a8_内部类.s3_匿名类; public abstract class Hero { String name; //姓名 float hp; //血量 float armor; //护甲 int moveSpeed; //移动速度 public abstract void attack(); public static void main(String[] args) { ADHero adHero = new ADHero(); adHero.attack(); System.out.println(adHero); Hero hero = new Hero() { @Override public void attack() { System.out.println("新的进攻手段!"); } }; hero.attack(); System.out.println(hero); } }

10.3.1 使用外部局部变量

法 1: 外部局部变量必须是 final

package11个程序_接口与继承.a8_内部类.s3_匿名类.使用外部局部变量; public abstract class Hero { public abstract void attack(); public static void main(String[] args) { final int damage = 5; Hero hero = new Hero() { @Override public void attack() { System.out.printf("新的进攻手段,造成 %d 的伤害\n", damage); } }; hero.attack(); } }

等价于 法2:

package11个程序_接口与继承.a8_内部类.s3_匿名类.使用外部局部变量; public abstract class Hero1 { public abstract void attack(); public static void main(String[] args) { int damage = 5; class AnnoymousHero extends Hero1{ int damage; public AnnoymousHero(int damage){ this.damage = damage; } public void attack(){ damage = 10; System.out.printf("新的进攻手段,造成 %d 的伤害!", this.damage); } } Hero1 hero1 = new AnnoymousHero(damage); hero1.attack(); } }

10.4 本地类

本地类:有名字的匿名类

package11个程序_接口与继承.a8_内部类.s4_本地类; public abstract class Hero { String name; //姓名 float hp; //血量 float armor; //护甲 int moveSpeed; //移动速度 public abstract void attack(); public static void main(String[] args) { class SomeHero extends Hero{ @Override public void attack() { System.out.println(name + " 新的进攻手段!"); } } SomeHero someHero = new SomeHero(); someHero.name = "寒冰射手"; someHero.attack(); } }

10.5 练习

创建匿名类 Item 抽象方法 disposable()

package11个程序_接口与继承.a8_内部类.练习; public abstract class Item { String name; int price; public abstract boolean disposable(); public static void main(String[] args) { Item item = new Item() { @Override public boolean disposable() { name = "血瓶"; System.out.println(name + " 是一次性的吗?"); return true; } }; System.out.println(item.disposable()); } }

11 默认方法

接口也可以提供具体方法了

为什么要有这个功能? 答案:要为某个接口新加一个方法,则所有继承该接口的类都需要修改,很麻烦!

public interface Mortal { public void die(); default public void revive() { System.out.println("本英雄复活了"); } }

11.1 练习

为AD接口,加默认方法 attack() 为AP接口,加默认方法 attack() 问: ADAPHero 同时实现 AD, AP 接口,那么 ADAPHero 对象调用 attack() 时,调用哪个接口的 attack()?

答案: 实现多个接口同时,这些接口中实现了同样的默认方法, 那实现的子类必须要实现这个默认方法, 因为不知道要选择哪个方法

而要默认方法只有一个,那就可以不用实现 如AP实现了默认方法,AD没实现,那么两个都实现的子类也不用实现 或只实现一个接口,那么子类也不用实现

12 综合练习

Animal

package11个程序_接口与继承.a9_综合练习; public abstract class Animal { public int legs; public Animal(){ System.out.println("创建了没有腿的动物!"); } public Animal(int legs){ this.legs = legs; System.out.println("创建了 " + legs + " 条腿的动物"); } public abstract void eat(); public void walk(){ System.out.println("该动物是用" + this.legs + "条腿走路的"); } }

Pet

package11个程序_接口与继承.a9_综合练习; public interface Pet { public String getName(); public void setName(String name); public void paly(); }

Spider

package11个程序_接口与继承.a9_综合练习; public class Spider extends Animal{ public Spider(){ super(8); System.out.println("每个蜘蛛都是8条腿"); } @Override public void eat() { System.out.println("蜘蛛在吃虫"); } }

Cat

package11个程序_接口与继承.a9_综合练习; public class Cat extends Animal implements Pet{ private String name; public Cat(){ this(null); System.out.println("该猫没有名字"); } public Cat(String name){ super(4); this.name = name; } @Override public void eat() { System.out.println(this.name + "在吃鱼"); } @Override public String getName() { return this.name; } @Override public void setName(String name) { this.name = name; } @Override public void paly() { System.out.println(this.name + "在玩耍"); } }

Fish

package11个程序_接口与继承.a9_综合练习; public class Fish extends Animal implements Pet{ private String name; public Fish(){ } @Override public void eat() { System.out.println(this.name + "在吃更小的鱼"); } @Override public String getName() { return this.name; } @Override public void setName(String name) { this.name = name; } @Override public void paly() { System.out.println(this.name + "在玩耍"); } }

测试

package11个程序_接口与继承.a9_综合练习; public class test { public static void main(String[] args) { Cat cat = new Cat("猫a"); Spider spider = new Spider(); Fish fish = new Fish(); cat.eat(); cat.getName(); cat.paly(); spider.eat(); fish.getName(); fish.paly(); } }

最新回复(0)