在这里我就不说多态是什么了,因为今天的这个问题重点其实不在多态。
我在学习多态时想了一个很奇怪的问题,多态可以做到让传参更简便,问题就在这个参数上。
我们平常在传递参数的时候,总会以一个父类,或者接口来当作参数,就比如说:
java.lang.Object中的方法:
equals(Object obj)
指示一些其他对象是否等于此。
其实这就是一种简单的运用,因为所有的类都继承了Object,所以这个方法的参数是任意类,我们也可以缩小范围,比如将参数定义为Person person,然后Person类是学生类和老师类的父类,此时参数中就可以容纳两种不同的对象。
但是,问题来了,如果我们想要容纳的是,指定的一些特定范围的对象呢?
话不多说,举例:
//首先定义三个接口,一个是本能,一个是攻击,一个是防御
//本能
interface Instinct {
void eat();
}
//攻击
interface Attack {
void fight(); // 进攻
}
//退缩
interface Cower {
void defense(); // 防御
}
//下面是两个父类,其他的类都继承了二者其一
//人类
class Person elements Instinct {
@Override
public void eat(){
System.out.println("人吃饭") ;
}
}
//动物类
class Animal implements Instinct {
@Override
public void eat() {
System.out.println("动物吃饭");
}
}
//子类
//警察是人,同时可以攻击
class Police extends Person implements Attack {
@Override
public void fight() {
System.out.println("开枪");
}
}
//学生也是人,可他只会尖叫(算是防御吧)
class Student extends Person implements Cower {
@Override
public void defense() {
System.out.println("尖叫");
}
}
// 食肉动物
class Carnivora extends Animal implements Attack {
@Override
public void fight() {
System.out.println("撕咬");
}
}
// 食草动物
class Herbivore extends Animal implements Cower {
@Override
public void defense() {
System.out.println("逃跑");
}
}
}
有没有什么感觉?
没有的话继续看,Java的多态在引入参数的时候会有一些小问题。
先看一段没有问题的代码:
public static void main(String[] args) {
Person person1 = new Police() ; // 警察
Person person2 = new Student() ; // 学生
Animal animal1 = new Carnivora() ; // 食肉动物
Animal animal2 = new Herbivore() ; // 食草动物
aMan(person1) ;
aMan(person2) ;
//以下注释的两句是在编译之前就会出错的。
//aMan(animal1) ;
//aMan(animal2) ;
}
// 我需要人来执行一个任务
public static void aMan(Person person) {
person.eat() ; //没错,我可以正常执行
}
可是,思考一下下面的一段代码:
public static void main(String[] args) {
Person person1 = new Police() ; // 警察
Person person2 = new Student() ; // 学生
Animal animal1 = new Carnivora() ; // 食肉动物
Animal animal2 = new Herbivore() ; // 食草动物
//以下注释的语句是在编译之前就会出错的。
aMan(person1) ;
//aMan(person2) ;
aMan(animal1) ;
//aMan(animal2) ;
}
// 天气不错,厉害的要吃顿好的,然后练练手
public static void sport(Attack att) {
// 先吃好的
// 哎呀!没有eat()方法,算了,先看看它是人还是动物吧
if (att instanceof Instinct) {
((Instinct) att).eat();
}else {
System.out.println("不好意思,你不能吃") ;
}
//哈哈,吃饱了,运动运动
att.fight() ;
}
观察sport方法,由于参数是Attack接口,所以对象只具有fight方法,如果想调用eat方法,则需要判断继承了Person类还是Animal类……然后强转,才可以使用。
其实这是一个很尴尬的过程,明明同一个对象,因为继承实现了俩不同的东西,导致如果想调用其中某个方法,就得先强转才可以……很不自由。
对此,我觉得,如果是我的话我会加一个机制:
<? extends E elements T> ins ;
此时d sport方法便可以写成:
// 天气不错,厉害的要吃顿好的,然后练练手
public static void sport(<? elements Instinct, Attack> att) {
// 先吃好的
att.eat() ;
//哈哈,吃饱了,运动运动
att.fight() ;
}
这样做的好处还是很明显的。
我不太清楚为什么多态没有这样的实现手段,也有可能它存在,只是我不知道它的语法罢了。