文章目录

  • 接口
    • 创建接口
    • 使用接口
    • 什么样的情况下该使用接口?
  • 对象转型
    • 明确引用类型与对象类型的概念
    • 子类转父类(向上转型)
    • 父类转子类(向下转型)
      • 总结
    • 没有继承关系的两个类,互相转换,一定会失败
    • 实现类转换成接口(向上转型)
    • 接口转换成实现类(向下转型)
    • instanceof
  • 重写
  • 多态
    • 操作符的多态
    • 类的多态
      • 观察类的多态现象
      • 类的多态条件以及作用
  • 多态和继承的区别
  • 隐藏

接口

接口就像是一种约定,我们约定某些英雄是物理系英雄,那么他们就一定能够进行物理攻击。

在设计LOL的时候,进攻类英雄有两种,一种是进行物理系攻击,一种是进行魔法系攻击
这时候,就可以使用接口来实现这个效果

创建接口

创建一个接口 File->New->Interface
AD ,声明一个方法 physicAttack 物理攻击,但是没有方法体,是一个“空”方法

package charactor;public interface AD {//物理伤害public void physicAttack();
}

设计一类英雄,能够使用物理攻击
设计一类英雄,能够使用物理攻击,这类英雄在LOL中被叫做AD
类:ADHero
继承了Hero 类,所以继承了name,hp,armor等属性
实现某个接口,就相当于承诺了某种约定。所以,实现了AD这个接口,就必须提供AD接口中声明的方法physicAttack()
实现在语法上使用关键字 implements

package j2se;public class ADHero extends Hero implements AD{//父类Hero只有有参构造方法,继承类就需要显式声明重写父类构造函数public ADHero(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void physicAttack(){System.out.println("进行了物理攻击");}
}

魔法攻击接口

package charactor;public interface AP {public void magicAttack();
}

设计一类英雄,只能使用魔法攻击
继承了Hero 类,所以继承了name,hp,armor等属性
同时,实现了AP这个接口,就必须提供AP接口中声明的方法magicAttack()。实现在语法上使用关键字 implement

package j2se;public class APHero extends Hero implements AP {public APHero(String name){super(name);}@Overridepublic void magicAttack(){System.out.println("进行了魔法攻击");}
}

设计一类英雄,既能进行物理攻击,又能进行魔法攻击

package j2se;public class ADAPHero extends Hero implements AD,AP{public ADAPHero(String name){super(name);}@Overridepublic void physicAttack(){System.out.println("进行了物理攻击");}@Overridepublic void magicAttack(){System.out.println("进行了魔法攻击");}
}

使用接口

与类不同,接口不能new,不能直接创建一个借接口对象,对象只能通过类来创建。但是可以声明接口类型的变量,引用实现了接口的类对象

AD hero1 = new ADHero("hanbing");
System.out.println(hero1.physicAttack());

hero1是AD的类型变量,但是引用了ADHero类型的对象,之所以能赋值,是因为ADHero实现了AD接口,如果一个类型实现了多个接口,那么这种类型的对象就可以被赋值给任意接口类型的变量。
hero1可以调用AD接口的方法,也只能调用AD接口的方法(不能调用ADHero类中的其他实例或者类方法),实际执行时,执行的是具体实现类的代码。如下:

package lianxi;public class ADHero implements AD{protected String name;public ADHero(String name) {this.name = name;}public static void test(){System.out.println("ADHero test");}@Overridepublic void physicAttack(){System.out.println("进行了物理攻击");}public static void main(String[] args) {AD hero1 = new ADHero("hb");hero1.physicAttack();//执行ADHero中的physicAttack方法hero1.test();//错误}
}

使用接口的目的是:降低耦合,提高灵活性

什么样的情况下该使用接口?

如上的例子,似乎要接口,不要接口,都一样的,那么接口的意义是什么呢
学习一个知识点,是由浅入深得进行的。 这里呢,只是引入了接口的概念,要真正理解接口的好处,需要更多的实践,以及在较为复杂的系统中进行大量运用之后,才能够真正理解,比如在学习了多态之后就能进一步加深理解。

练习-接口
设计一个治疗者接口:Healer
该接口声明有方法: heal()
设计一个Support类,代表辅助英雄,继承Hero类,同时实现了Healer这个接口

package j2se;public class Supper extends Hero implements Healer {public Supper(String name){super(name);}@Overridepublic void heal(){System.out.println(this.name+"加了点血");}public static void main(String[] args) {Supper ad=new Supper("teemo");//实例化对象,调用构造方法ad.heal();}
}

对象转型

父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中定义而父类中没有的属性或方法,父类引用无法调用。子类重定义父类已有的属性,父类引用调用的还是本类的属性值。子类重定义父类已有的方法时,父类引用调用的是子类重写过的方法(这里只能调用实例方法,因为其实动态绑定的)。

明确引用类型与对象类型的概念

首先,明确引用类型与对象类型的概念
在这个例子里,有一个对象 new ADHero(), 同时也有一个引用ad
对象是有类型的, 是ADHero
引用也是有类型的,是ADHero
通常情况下,引用类型和对象类型是一样的
接下来要讨论的类型转换的问题,指的是引用类型和对象类型不一致的情况下的转换

package charactor;public class Hero {public String name;protected float hp;    public static void main(String[] args) {    ADHero ad = new ADHero();}
}

所谓的转型,是指当引用类型和对象类型不一致的时候,才需要进行类型转换。类型转换有时候会成功,有时候会失败
判别到底能否转换成功?
把右边的当做左边来用,看能否说的通

子类转父类(向上转型)

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

右边ad引用所指向的对象的类型是 物理攻击英雄
左边h引用的类型是 普通英雄
把物理攻击英雄 当做 普通英雄,说不说得通? 说得通,就可以转
所有的子类转换为父类,都是说得通的

父类转子类(向下转型)

总结:子类先指向父类,然后再把这个子类转子类就可以转
父类转子类,有的时候行,有的时候不行,所以必须进行强制转换。
强制转换的意思就是 转换有风险,风险自担。
什么时候可以?

1.        Hero h =new Hero();
2.        ADHero ad = new ADHero();
3.        h = ad;
4.        ad = (ADHero) h;
5. 'ad是ADHero类型的,也是Hero类型的'
6. "因为类型转换,所以h是ADHero类型的,也是Hero类型的。如果没有第三句 h就不是ADHero类型的"

第3行,是子类转父类,一定可以的
第4行,就是父类转子类,所以要进行强转
h这个引用,所指向的对象是ADHero, 所以第4行,就会把ADHero转换为ADHero,就能转换成功。
什么时候转换不行呢?

Base();//父类
Child();//子类
Base b = new Base();
Child c = Child(b);//这样是不行的

语法上java不会报错,但是运行时会抛出出错,错误为类型转换异常。
一个父类的变量能不能转换为一个子类的变量,取决于这个父类变量的动态类型(即引用的对象类型)是不是这个子类或者这个子类的

总结

可以通过instanceof关键字判断给的一个父类变量能不能转换为一个子类的变量,从而安全地进行类型转换。

package charactor;public class Hero {public String name;protected float hp;public boolean equals(Object o){//这里是传入Object类型或其子类型的对象(new name(),把o引用指向object对象或者子类对象)if(o instanceof Hero){Hero h = (Hero) o;return this.hp == h.hp;}return false;}public static void main(String[] args) {Hero h1= new Hero();h1.hp = 300;Hero h2= new Hero();h2.hp = 400;Hero h3= new Hero();h3.hp = 300;System.out.println(h1.equals(h2));System.out.println(h1.equals(h3));}
}
    public boolean equals(Object o){//这里是传入Object类型或其子类型的对象(new name(),把o引用指向object对象或者子类对象)if(o instanceof Hero){Hero h = (Hero) o;return this.hp == h.hp;}return false;}

其中:

  • public boolean equals(Object o)这里是传入Object类型或其子类型的对象(new name(),把o引用指向object对象或者子类对象),object o = new name(),子类转父类一定可以 。设置为object,就不会出现传入错误的情况。如果是(ADHero o),则传入new Hero()就会出错
  • if(o instanceof Hero)判断传入的对象是不是Hero类型,或其子类型的
  • Hero h = (Hero) o; (Hero) o是强制 父类转子类,其之所以成功。是应为object的引用o指向了传入的对象new name(),而传入的对象通过上一步的判断,其是Hero类或Hero类的子类
  • return this.hp == h.hp;,h.hp是访问的传入对象的hp,父类引用指向子类对象,引用访问方法时,如果子类有重写方法,则访问子类的方法。但是不能访问子类中新加的属性和方法,也就是说在父类中没有定义的属性和方法。

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

虽然ADHeroAPHero都继承了Hero,但是彼此没有互相继承关系
比如:“把魔法英雄当做物理英雄来用”,在语义上也是说不通的

实现类转换成接口(向上转型)

总结:也就是说有实现接口方法的类类型对象才能转换为接口,接口直接转换为类类型会失败,需要先转换
引用ad指向的对象是ADHero类型,这个类型实现了AD接口
10行: 把一个ADHero类型转换为AD接口
从语义上来讲,把一个ADHero当做AD来使用,而AD接口只有一个physicAttack方法,这就意味着转换后就有可能要调用physicAttack方法,而ADHero一定是有physicAttack方法的,所以转换是能成功的。(转换为AP接口就不行)

package charactor;public class Hero {public String name;protected float hp;public static void main(String[] args) {ADHero ad = new ADHero();AD adi = ad;         }
}

接口转换成实现类(向下转型)

10行: ad引用指向ADHero, 而adi引用是接口类型:AD,实现类转换为接口,是向上转型,所以无需强制转换,并且一定能成功
12行: adi实际上是指向一个ADHero的,所以能够转换成功
14行: adi引用所指向的对象是一个ADHero,要转换为ADAPHero就会失败。(假设能够转换成功,那么就可以使用magicAttack方法,而adi引用所指向的对象ADHero是没有magicAttack方法的。)

instanceof

instanceof Hero 判断一个引用所指向的对象,是否是Hero类型,或者Hero的子类

System.out.println(h1 instanceof ADHero);
Hero h = ad 这一行是没错 是由子转父,
AD adi = (AD) h; 这一行是因为h指向ADHero,强行转为AD也是可行的,最后达到父转子
APHero ap = (APHero) adi; 这个adi是指向AD的,不能强行转向APhero,所以这里有问题

重写

子类可以继承父类的对象方法
在继承后,重复提供该方法,就叫做方法的重写
又叫覆盖 override
比如:父类Item有个方法

package j2se;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 bloodBottle = new Item();bloodBottle.name = "血瓶";bloodBottle.price = 50;Item shoots = new Item();shoots.name = "草鞋";shoots.price = 300;Item sword = new Item();sword.name = "长剑";sword.price = 350;bloodBottle.effect();'子类调用effect方法,就会执行重写的方法,而不是从父类的方法'LifePotion lp = new LifePotion();lp.effect();}
}
package j2se;public class LifePotion extends Item{'重写父类的effect方法'public void effect(){System.out.println("血瓶使用后,可以回血");}
}

如果没有重写这样的机制,也就是说LifePotion这个类,一旦继承了Item,所有方法都不能修改了。
但是LifePotion又希望提供一点不同的功能,为了达到这个目的,只能放弃继承Item,重新编写所有的属性和方法,然后在编写effect的时候,做一点小改动.
这样就增加了开发时间和维护成本

多态

操作符的多态
+ 可以作为算数运算,也可以作为字符串连接
类的多态
父类引用指向子类对象

操作符的多态

同一个操作符在不同情境下,具备不同的作用
如果+号两侧都是整型,那么+代表 数字相加
如果+号两侧,任意一个是字符串,那么+代表字符串连接

类的多态

观察类的多态现象

观察类的多态现象:

  1. i1i2都是Item类型
  2. 都调用effect方法
  3. 输出不同的结果
    多态: 都是同一个类型,调用同一个方法,却能呈现不同的状态
package property;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 i1= new LifePotion();Item i2 = new MagicPotion();System.out.print("i1  是Item类型,执行effect打印:");i1.effect();System.out.print("i2也是Item类型,执行effect打印:");i2.effect();}}

类的多态条件以及作用

要实现类的多态,需要如下条件

  1. 父类(接口)引用指向子类对象
  2. 调用的方法有重写

那么多态有什么作用是什么?
不使用多态时:
如果不使用多态,
假设英雄要使用血瓶和魔瓶,就需要为Hero设计两个方法
useLifePotionuseMagicPotion
除了血瓶和魔瓶还有很多种物品,那么就需要设计很多很多个方法,比如
usePurityPotion 净化药水
useGuard 守卫
useInvisiblePotion 使用隐形药水
等等等等

package charactor;import property.LifePotion;
import property.MagicPotion;public class Hero {public String name;protected float hp;public void useLifePotion(LifePotion lp){lp.effect();}public void useMagicPotion(MagicPotion mp){mp.effect();}public static void main(String[] args) {Hero garen =  new Hero();garen.name = "盖伦";LifePotion lp =new LifePotion();MagicPotion mp =new MagicPotion();garen.useLifePotion(lp);garen.useMagicPotion(mp);}}

使用多态
如果物品的种类特别多,那么就需要设计很多的方法
比如useArmoruseWeapon等等
这个时候采用多态来解决这个问题
设计一个方法叫做useItem,其参数类型Item(是为了让父引用指向子类对象)
如果是使用血瓶,调用该方法
如果是使用魔瓶,还是调用该方法
无论英雄要使用什么样的物品,只需要一个方法即可

package charactor;import property.Item;
import property.LifePotion;
import property.MagicPotion;public class Hero {public String name;protected float hp;public void useItem(Item i){i.effect();}public static void main(String[] args) {Hero garen =  new Hero();garen.name = "盖伦";LifePotion lp =new LifePotion();MagicPotion mp =new MagicPotion();        garen.useItem(lp);'这里有一个子类型向父类转换Item i = lp'garen.useItem(mp);             }
}

练习:
immortal是不朽的,不死的意思
mortal就是终有一死的,凡人的意思

  1. 设计一个接口
    接口叫做Mortal,其中有一个方法叫做die
  2. 实现接口
    分别让ADHero,APHero,ADAPHero这三个类,实现Mortal接口,不同的类实现die方法的时候,都打印出不一样的字符串
  3. 为Hero类,添加一个方法,在这个方法中调用 m的die方法。
public void kill(Mortal m)
  1. 在主方法中
    首先实例化出一个Hero对象:盖伦
    然后实例化出3个对象,分别是ADHero,APHero,ADAPHero的实例
    然后让盖伦 kill 这3个对象
public class Hero {String name; //姓名float hp; //血量float armor; //护甲int moveSpeed; //移动速度//带一个参数的构造方法public Hero(String name){System.out.println("创建"+ name);this.name = name;}public void kill(mortal m){m.die();}//带两个参数的构造方法
/*   public Hero(String name,float hp){this(name);System.out.println("两个参数的构造方法");this.hp = hp;}*/public static void main(String[] args) {//        Hero teemo =  new Hero("提莫",383);Hero teemo =  new Hero("提莫");ADHero hanbing = new ADHero("寒冰");APHero Karsatin = new APHero("卡萨丁");ADAPHero EZ = new ADAPHero("EZ");//     System.out.println(teemo.name);teemo.kill(hanbing);teemo.kill(Karsatin);teemo.kill(EZ);}
package j2se;public class ADHero extends Hero implements AD,mortal{public ADHero(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void physicAttack(){System.out.println("进行了物理攻击");}@Overridepublic void die(){System.out.println(this.name +"被杀死了");}}

多态和继承的区别

看上例中继承和多态的掺杂,就弄混了。
继承是子类使用父类的方法和属性(除了private),而多态是,通过子类重写父类的方法,在父类中通过父类引用指向子类实例调用子类的方法。

继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

多态与继承、方法重写密切相关,我们在方法中接收父类类型作为参数,在方法实现中调用父类类型的各种方法。当把子类作为参数传递给这个方法时,java虚拟机会根据实际创建的对象类型,调用子类中相应的方法(存在方法重写时)。
多态性是指允许不同类bai的对象对同一消息作出响应。多态性du包括参数化多态性和包含zhi多态性。多态性语言具有灵活、dao抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。
多态的表现形式有重载和覆盖两种形式。
重载(overload),是发生在同一类中。与什么父类子类、继承毫无关系。
标识一个函数除了函数名外,还有函数的参数(个数和类型)。也就是说,一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同。
他们之间毫无关系,是不同的函数,只是可能他们的功能类似,所以才命名一样,增加可读性,仅此而已!
再说覆盖(override),是发生在子类中!也就是说必须有继承的情况下才有覆盖发生。
我们知道继承一个类,也就有了父类了全部方法,如果你感到哪个方法不爽,功能要变,那就把那个函数在子类中重新实现一遍。
这样再调用这个方法的时候,就是执行子类中的过程了。父类中的函数就被覆盖了。(当然,覆盖的时候函数名和参数要和父类中完全一样,不然你的方法对父类中的方法就不起任何作用,因为两者是两个函数,毫不关系)
在java中
高内聚,低耦合。
继承就可以降低代码的耦合,这样编写代码,在你以后修改一处时,就不会牵扯很多的累,方便以后的修改和升级。

隐藏

与重写类似,方法的重写是子类覆盖父类的对象方法

隐藏,就是子类覆盖父类的类方法
父类有一个类方法 :battleWin

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

子类隐藏父类的类方法

package charactor;public class ADHero extends Hero implements AD{@Overridepublic 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();}}

java基础/接口与继承1(0.96万字)相关推荐

  1. 《Java程序设计》实验报告——Java的接口与继承

    浙江理工大学 <Java程序设计>  实验报告  20 19-20 20学年第 1学期      学  院 信息学院 班  级 计算机科学与技术18(3) 姓  名 申屠志刚 学  号 2 ...

  2. java接口比继承优秀的地方,实现和继承的区别 java 实现接口和继承有什么区别...

    Java中继承和实现的区别 理论上:类只能单继承,接口可以多继承(接口应该叫实现): 实践上:小编们说类的继承一般继承的是事物的属性,如:姓名,年龄,性别 等,而接口的继承(或者说实现)一般是继承事物 ...

  3. Java中接口如何继承接口呢?

    转自: Java中接口如何继承接口呢? 下文讲述一个接口继承另一个接口的实现方式,如下所示: 实现思路:接口继承接口,采用的extends关键字 例:   接口继承接口的示例分享 interface ...

  4. java中接口可以继承接口吗?

    java中接口可以继承接口吗? java中不允许类多重继承的主要原因是:如果A同时继承B和C,而假如B和C同时有一个d方法,A如何决定该继承哪一个呢? 但接口不存在这样的问题,接口中全都是抽象方法,继 ...

  5. Java的接口与继承

    大多数人认为,接口的意义在于顶替多重继承.众所周知Java没有c++那样多重继承的机制,但是却能够实作多个接口.其实这样做是很牵强的,接口和继承是完全不同的东西,接口没有能力代替多重继承,也没有这个义 ...

  6. java基础-接口与实现

    接口的定义和类的定义很相似,可以分为接口声明和接口体积,和类不同的是,使用关键字interface来声明自己是一个接口. 格式如下; interface 接口的名字 这里需要注意的是: 1.如果一个非 ...

  7. java基础--接口(interface)

    接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承接口的抽象方法. 接口并不是类,编写接口 ...

  8. Java的接口、继承与多态

    接口 java只支持单继承,即一个类只能有一个父类,因此需要接口来实现多重继承. 接口的定义 类和接口的区别:一个类通过继承接口的方式,从而来继承接口的抽象方法.类描述对象的属性和方法,接口则包含类要 ...

  9. java基础[接口]

    接口作用:将两个不同的东西连接起来,让他们共同去工作! 具体类:定义某一具体的事物: 抽象类:定义某一类不同种的事物: 接口:定义不同类型的不同种事物,但是却有共同的行为,注重事物的行为,而不是事物的 ...

最新文章

  1. OpenCV中minAreaRect()最小外接矩形 cvBoxPoints()计算矩形顶点 RotatedRect和CvBox2D详解
  2. Git每次推送时都会询问用户名
  3. python创建列表_python创建与遍历List二维列表的方法
  4. SAP FICO与金蝶财务软件的区别
  5. 鸿蒙智慧电视,华为的鸿蒙电视与智能电视有什么区别
  6. linux系统账户口令管理
  7. mysql 脚本命令大全,linux 常用Mysql脚本命令
  8. java搭建线程池框架_JAVA线程池经管及分布式HADOOP调剂框架搭建
  9. 你爱我,我爱你,IP被封很头疼【Python爬虫实战:ip代理js逆向采集】
  10. 分享不会迟到,只会来的晚一点——16倍速视频播放
  11. 图解机器学习算法(7) | 随机森林分类模型详解(机器学习通关指南·完结)
  12. kali linux(全版本)详细安装w3af指南(文内提供成品镜像下载)
  13. vm虚拟机出现目标主机不支持CPUID的情况
  14. C语言学习-翁凯(第四章笔记)
  15. 计算机应用基础——计算机硬件(三)
  16. 程序员怎样才能写出一篇好的博客或者技术文章
  17. 服务器和交换机物理连接_交换机发生网络通信故障怎么解决?
  18. 基于云服务创建实时运营数据分析服务(一)
  19. Mac wifi 卡死
  20. 2022年暑期实习 PwC AC 普华永道信息技术 待遇+笔试+面试信息

热门文章

  1. 【有福利,手慢无】相册网送您免费洗50张照片
  2. 安卓注解处理器-processor
  3. VirtualBox虚拟机几种网络连接方式介绍
  4. 学习计算机组成原理课程,推荐书籍,写CPU(随做更新
  5. 第7章 CustomView绘图进阶
  6. 微软 Win10 更新再出 bug
  7. 小米笔记本 wifi linux,被小米笔记本的WiFi坑了一道
  8. matlab hanning和hann,哪位大侠能告知——为什么在MATLAB2012中不能调研(汉宁)窗函...
  9. 华三模拟器:IPV6路由实验
  10. 单面打印机打印双面小册子