(一)多态的实现
对象的多种形态
1. 引用多态
父类的引用可以指向本类的对象;
父类的引用可以指向子类的对象;
public class anmals(){
}
public class dog extends animals {
}
public static void main(String[] , args){
animals obj1 = new animals();//父类的引用obj1指向本类的对象;
animals obj2 = new dog();//父类的引用obj2指向子类的对象;
}
2.方法多态
创建本类对象时,调用的方法为本类的方法;
创建子类对象时,调用的方法为子类重写的方法或者继承的方法;
public class anmals(){
public void running(){
System.out.println("动物具有跑步的能力");
}
}
public class dog extends animals {
public void running(){
System.out.println("狗具有跑步的能力");
}
}
public class cat extends animals {
**这里没有重写从父类继承来的running()方法**
}
public static void main(String[] , args){
animals obj1 = new animals();//父类的引用obj1指向本类的对象;
obj1.running();//创建本类对象时,调用的方法为本类的方法;
animals obj2 = new dog();//创建子类对象时,调用的方法为子类重写的方法;
obj2.running();//创建本类对象时,调用的方法为本类的方法;
animals obj3 = new cat();//父类的引用obj2指向子类的对象;
obj3.running();//创建子类对象时,调用的方法为继承的方法;
}
运行结果:
动物具有跑步的能力
狗具有跑步的能力
动物具有跑步的能力
(二)多态中的引用类型转换
1. 向上类型转换(转换方式:隐式/自动类型转换),是小类型到大类型的转换;(无风险)
2. 向下类型转换(转换方式:强制类型转换),是大类型到小类型;(有风险)
如何避免风险问题?
3.使用instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题;
语法:
if(父类 instanceof 子类){
子类 (子类)对象 = (子类)父类对象;
}else{
……..
}
public static void main(String[] , args){
dog dog_7 = new dog();
if( animals instanceof dog){
animals animals_7 = dog_7 ;//向上类型转换 , 自动类型转换
}else{
System.out.println("无法进行类型转换 转换成为dog类型");
}
dog dog_9 =(dog)animals;//强制类型转换
if(animals instanceof cat){
cat cat_7 = (cat)animals;//1.编译时,cat类型;2.运行时,dog类型;
}else{
System.out.println("无法进行类型转换 转换成为cat类型");
}
}
运行结果:
无法进行类型转换 转换成为cat类型
1. 语法定义:
抽象类前使用abstarct关键字修饰,则该类为抽象;
2.抽象类的使用场景:
a. 在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法;
b. 从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为子类的模板,从而避免了子类设计的随意性;
3.抽象类的作用:
限制规定子类必须实现某些方法,但不关注实现细节;
4.抽象类的使用方法:
a. abstarct定义抽象类;
b. abstarct定义抽象方法,只有声明,不需要实现;
c. 包含抽象方法的类是抽象类;
d. 抽象类中可以包含普通的方法,也可以没有抽象方法;
e. 抽象类不能直接创建,可以定义引用变量;
比如:
创建抽象类:myAnimals
public abstarct class myAnimals{
public abstarct void run();
public abstarct void eat();
}
创建子类Dog,并继承父类myAnimals
public class Dog extends myAnimals{
//抽象父类myAnimals会强制继承他的子类必须实现方法run() ,eat()
public abstarct void run(){
System.out.println("狗具有跑的功能");
}
public abstarct void eat(){
System.out.println("狗具有吃东西的功能");
}
}
创建子类Cat,并继承父类myAnimals
public class Cat extends myAnimals{
public abstarct void run(){
System.out.println("猫具有跑的功能");
}
public abstarct void eat(){
System.out.println("猫具有吃东西的功能");
}
}
//测试类
public static void main( String[] , args){
myAnimals myanimals_7 = new Dog();//父类引用指向子类对象
myanimals_7.run();
myanimals_7.eat();
myAnimals myanimals_9 = new Cat();//父类引用指向子类对象
myanimals_9.run();
myanimals_9.eat();
}
运行结果:
狗具有跑的功能
狗具有吃东西的功能
猫具有跑的功能
猫具有吃东西的功能
(三)多态中的接口
a. 接口的定义:类是一种具体实现体,而接口定义了某一批类所需要遵循的规范,接口不关心这些类内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法。
b. 语法:和类定义不同,定义接口,不再使用class关键字,而是使用interface关键字。
c. 接口定义的基本语法:
[修饰符]interface 接口名 [extends 父接口1 , 父接口 2….]
{
零个到多个常量定义…
零个到多个抽象方法的定义…
}
接口就是用来被继承,被实现的,修饰符,一般建议用public
注意:不能使用private 和 protected修饰接口;
d. 接口中定义的常量:
1)接口中的属性是常量,即使定义时,不添加 public static final 修饰符,系统也会自动加上;
2)接口中的方法只能是抽象方法,总是使用,即使定义时不添加 public static final 修饰符,系统也会自动加上;
e.接口的使用
1)一个类可以实现一个或者多个接口,实现接口使用implements关键字。java中一个类只能继承一个父类,不够灵活,通过实现多个接口作为补充;
继承父类实现接口的语法:
[修饰符] class 类名 extends 父类 implement 接口1, 接口2…..
{
类体部分//如果继承了抽象类,需要实现继承的抽象方法;要实现接口中的抽象方法。
}
如果要继承父类,继承父类必须在实现接口之前!!
2)接口在使用过程中,还经常与匿名内部类配合使用;
匿名内部类:就是没有名字的内部类,多用于关注实现而不关注实现的名称
语法:
Interface i = new Interface(){
public void method(){
System.out.println(“匿名内部类实现接口的方式”);
}
};
比如:
创建抽象类:myAnimals
public abstarct class myAnimals{
public abstarct void run();
public abstarct void eat();
}
//创建一个接口
public interface IclimbTree{
public void climbtree();
}
创建子类Dog,并继承父类myAnimals
public class Dog extends myAnimals{
//抽象父类myAnimals会强制继承他的子类必须实现方法run() ,eat()
public abstarct void run(){
System.out.println("狗具有跑的功能");
}
public abstarct void eat(){
System.out.println("狗具有吃东西的功能");
}
}
创建子类Cat,并继承父类myAnimals
public class Cat extends myAnimals implements IclimbTree{
public abstarct void run(){
System.out.println("猫具有跑的功能");
}
public abstarct void eat(){
System.out.println("猫具有吃东西的功能");
}
public abstarct void climbTree(){
System.out.println("猫具有了爬树功能");
}
}
//创建一个类 fly, 并实现接口
public class fly implements climbTree {
@Override
public void climbtree() {
// TODO Auto-generated method stub
System.out.println("苍蝇具有爬树的功能!");
}
}
//测试类
public static void main( String[] , args){
/*
myAnimals myanimals_7 = new Dog();//父类引用指向子类对象
myanimals_7.run();
myanimals_7.eat();
myAnimals myanimals_9 = new Cat();//父类引用指向子类对象
myanimals_9.run();
myanimals_9.eat();
*/
IclimbTree ic1 = new Cat();//接口引用指向实现了接口的对象;
ic1.climbtree();
IclimbTree ic2 = new fly();//接口引用指向实现了接口的对象;
ic2.climbtree();
//接口与匿名内部类配合使用;
IclimbTree ic3 = new IclimbTree(){
public void climbtree() {
// TODO Auto-generated method stub
System.out.println("使用匿名内部类的方法实现接口!");
}
};
//通过接口的引用来调用IclimbTree()方法
ic3.climbtree();
}
//也可以直接new一个接口,并调用climbtree()方法
new IclimbTree(){
public void climbtree() {
// TODO Auto-generated method stub
System.out.println("直接使用new接口并使用匿名内部类的方法实现接口");
}
}.climbtree();
运行结果:
猫具有了爬树功能
苍蝇具有爬树的功能!
使用匿名内部类的方法实现接口!
直接使用new接口并使用匿名内部类的方法实现接口
这下就彻底征服多态这个渣渣了~~