实际上,我也不太清楚这到底是什么,但目前来说只是找到了一个例子去解释这种实现方式(至于这个例子恰当与否,还有待探索)。
public class TestMain {
public static void main(String[] args) {
Thing thing = new Thing();
thing.iMoveAction = new MoveThing();
System.out.println(thing.iMoveAction.isAnimal(new Object()));
}
}
interface IMoveAction {
void move();
boolean isAnimal(Object object);
}
class Thing {
IMoveAction iMoveAction;
}
class MoveThing implements IMoveAction {
@Override
public void move() {
// TODO 自动生成的方法存根
}
@Override
public boolean isAnimal(Object object) {
// TODO 自动生成的方法存根
return false;
}
}当时,我是有这样的疑问,thing.iMoveAction是IMoveAction的接口对象,而new 出来的MoveThing()是一个实现了IMoveAction接口的MoveThing的类,为何能将一个类赋值给一个接口对象呢?(实际上联想到List list = new ArrayList<>();的例子,也就可以对这种方式习以为常。但终究是无法清晰地解释这种方式。)
由此涉及到对接口定义的思考,什么是接口?
接口是规范、规则、公共的要去统一实现的内容。
那么我可以这样理解:thing对象中有iMoveAction这样的一个规则对象,而new出来的MoveThing实际上也是拥有这样一个规则对象的。thing.iMoveAction= new IMoveThing();实际上做的就是——>将new出来的MoveThing()对象的规则赋值给thing.iMoveAction这个规则的对象,可以称之为“规则的移植复用”。
举个现实生活中的例子:国乒有自己的一套标准规则,国际上也是有乒乓球的标准规则的。但是因为国乒的强大,国际的乒乓球标准规则就套用了国乒的标准规则。此时,假设国乒是new出来的MoveThing(),国际是Thing对象。国乒(MoveThing)实现了的标准规则,现在被国际(拥有thing.iMoveAction对象)拿来用了。
所以此处,最后输出的内容thing.iMoveAction.isAnimal(new Object())实际输出的是MoveThing中isAnimal实现的方法的内容(也就是国乒定的标准规则)。
class Panda extends Thing{
}若此时再定义一个Panda类,然后进行以下代码运行:
Thing thing3 = new Thing();
thing3.iMoveAction = (IMoveAction) new Panda();
System.out.println(thing3.iMoveAction.isAnimal(new Object()));可以看到Panda类没有实现IMoveAction接口,只是继承了Thing类,所以在进行thing3.iMoveAction赋值时,编辑器会提示要么给new Panda()对象强制转换类型,要么让Panda类实现IMoveAction接口。此处选择了强制转换,编辑器没有报错,但——>运行时会提示转换类型错误,这个是很显然的,毕竟new出来的Panda()对象没有实现IMoveAction接口。
那么疑问出来了,Panda类只是没有实现IMoveAction接口,但是却拥有IMoveAction对象呀,为啥就不能赋值了呢?
——>还是使用乒乓球的例子:Panda类可以比作是国乒:国乒拥有一套“标准规则”,但只是私下的,并没有明文规定出来(也就是没有作为一套必定执行的标准去实现),那么国际上如果要拿去用,当然是不会被国际上那些不同国家的乒乓理事成员所承认的。所以,此处是不通过的,国乒得首先按照这套标准规则去明文实现才行(也就是Panda类首先得implements IMoveAction接口才行)。
当然,若某个子标准规则是继承了父标准规则,那么子标准规则也是可以用来给“实现了父标准规则的类的标准规则对象”赋值的。
interface ICrawlAction extends IMoveAction{
int moveDistance();
}
class Snake implements ICrawlAction{
@Override
public void move() {
// TODO 自动生成的方法存根
}
@Override
public boolean isAnimal(Object object) {
// TODO 自动生成的方法存根
return true;
}
@Override
public int moveDistance() {
// TODO 自动生成的方法存根
return 3;
}
}
此时ICrawlAction继承了IMoveAction,并定义了新的方法moveDistance()(相当于增加了规则)。此时Snake类实现了这个ICrawlAction接口,之后运行:
Thing thing4 = new Thing();
thing4.iMoveAction = new Snake();
System.out.println(thing4.iMoveAction.isAnimal(new Object()));
结果是:true。
可以看到,虽然ICrawlAction对IMoveAction进行了继承,但是并不影响对IMoveAction的对象赋值,因为赋值的时候使用的是“部分规则移植复用”,并不是全部,只要有相同的规则部分,均可以拿来使用。
ok,到此为止,以上例子为个人解释,或有不妥,欢迎探讨。若有不爽,憋着。
本文探讨了Java中接口与类赋值的概念,通过具体示例解析了接口对象如何指向其实现类的实例,以及子接口如何兼容父接口。
16万+

被折叠的 条评论
为什么被折叠?



