java向上转型
2015-09-30 11:11
531 查看
向上转型:将子类对象的引用转换为父类对象的引用,这就是向上转型。
”为新的类提供方法“这并不是继承中最重要的方面,其最重要的是用来表现新类和基类之间的关系。这种关系是”新类是现有类的一种类型“ 也就是is-a。例如:假设有一个称为Animal的代表动物的类和一个称为dog的导出类。继承可以保证基类中的所有的可继承方法(除了私有方法,不同包情况下的包访问权限方法)在导出类中也同样有效,所以能向基类发送的信息同样也可以向导出类发送。如:Animal有一个public的eat()方法,那么dog类也将具有此方法。这也就意味着dog对象也是一种类型的Animal。看一个例子:
在此例中,tune()方法可以接受Animal的引用,但在Dog.main()方法中,传递给tune方法的是一个Dog引用。刚开始我也不懂这到底是怎么回事,以为代码写错了呢。在tune()中,程序代码可以对Animal和它所有的导出类起作用,这将Dog引用转换为Aniaml引用的动作,就是向上转型。
2 为什么称为向上转型
传统的类继承图:基类置于页面的顶端,然后导出类逐渐向下。由导出类转型成基类,在继承图上是向上移动的,因此一般称为向上转型。
导出类是基类的一个超集。它可能比基类含有更多的方法,但它必须至少具备基类中的所有方法。在向上转型的过程中,类接口唯一可能发生的事情就是丢失方法,而不是获取它们。
3 再论向上转型
向上转型可以这么写: Shape s = new Circle();创建了一个Circle对象,并把他的引用赋值给Shape,看起来是错误的但是由于继承,Circle也是一种Shape,因此没有问题。
示例:
Circle.draw()
Circle.earse()
以前,我认为输出的答案应该是Shape.draw() Shape.earse().但是结果并不是那样。Shape s = new Circle();中的s是父类的引用,指向的确是子类的对象,编译器在执行的时候会先找子类对象中的方法,如果子类中由这个方法就会调用子类中的方法,如果没有才会查看父类中是否有这个方法。之所以能正确将引用指向Circle而不是Square或Triangle,是因为后期绑定。
4 域与静态方法
向上转型时调用域,会有什么样的结果呢,请往下看:
示例:
当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的,所以sup.field调用的是父类的field。当引用Sub要访问父类的域时,需要显示的指明super.field。
再看一个例子:
”为新的类提供方法“这并不是继承中最重要的方面,其最重要的是用来表现新类和基类之间的关系。这种关系是”新类是现有类的一种类型“ 也就是is-a。例如:假设有一个称为Animal的代表动物的类和一个称为dog的导出类。继承可以保证基类中的所有的可继承方法(除了私有方法,不同包情况下的包访问权限方法)在导出类中也同样有效,所以能向基类发送的信息同样也可以向导出类发送。如:Animal有一个public的eat()方法,那么dog类也将具有此方法。这也就意味着dog对象也是一种类型的Animal。看一个例子:
class Animal { public void eat(){} static void tune(Animal a){ //.... a.eat(); } } public class Dog extends Animal{ public static void main(String[] args){ Dog hashiqi = new Dog(); Animal.tune(hashiqi); //向上转型 } }
在此例中,tune()方法可以接受Animal的引用,但在Dog.main()方法中,传递给tune方法的是一个Dog引用。刚开始我也不懂这到底是怎么回事,以为代码写错了呢。在tune()中,程序代码可以对Animal和它所有的导出类起作用,这将Dog引用转换为Aniaml引用的动作,就是向上转型。
2 为什么称为向上转型
传统的类继承图:基类置于页面的顶端,然后导出类逐渐向下。由导出类转型成基类,在继承图上是向上移动的,因此一般称为向上转型。
导出类是基类的一个超集。它可能比基类含有更多的方法,但它必须至少具备基类中的所有方法。在向上转型的过程中,类接口唯一可能发生的事情就是丢失方法,而不是获取它们。
3 再论向上转型
向上转型可以这么写: Shape s = new Circle();创建了一个Circle对象,并把他的引用赋值给Shape,看起来是错误的但是由于继承,Circle也是一种Shape,因此没有问题。
示例:
public class Shape { public void draw(){System.out.println("Shape.draw()"} public void earse(){System.out.println("Shape.earse()"} } public class Square extends Shape{ public void draw(){System.out.println("Square.draw()"} public void earse(){System.out.println("Square.earse()"} } public class Circle extends Shape{ public void draw(){System.out.println("Circle.draw()"} public void earse(){System.out.println("Circle.earse()"} } public class Triangle extends Shape{ public void draw(){System.out.println("Triangle.draw()"} public void earse(){System.out.println("Triangle.earse()"} } public class Test{ public static void main(String[] args){ Shape s = new Circle(); s.draw(); s.erase(); } }输出:
Circle.draw()
Circle.earse()
以前,我认为输出的答案应该是Shape.draw() Shape.earse().但是结果并不是那样。Shape s = new Circle();中的s是父类的引用,指向的确是子类的对象,编译器在执行的时候会先找子类对象中的方法,如果子类中由这个方法就会调用子类中的方法,如果没有才会查看父类中是否有这个方法。之所以能正确将引用指向Circle而不是Square或Triangle,是因为后期绑定。
4 域与静态方法
向上转型时调用域,会有什么样的结果呢,请往下看:
示例:
class Super{ public int field = 0; public int getField(){ return field;} } public class Sub extends Super{ public int field = 1; public int getField(){ return field;} public int getSuperField{return super.field;} //显示调用父类的域 public static void main(String[] args){ Super sup = new Sub(); //向上转型 System.out.println("sup.field="+sup.field+", sup.getField()="+sup.getField()); Sub sub = new Sub(); //没有向上转型 System.out.println("sub.field="+sub.field+", sub.getField()="+sub.getField()+", sub.getSuperField()="+sub.getSuperField()); } } 输出: sup.field=0, sup.getField()=1; sub.field=1, sub.getField()=1, sub.getSuperField()=0;
当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的,所以sup.field调用的是父类的field。当引用Sub要访问父类的域时,需要显示的指明super.field。
再看一个例子:
class Super{ public static String staticGet(){ return "base class staticGet()"; } public String dynamicGet(){ return "base class dynamicGet()"; } } public class Sub extends Super{ public static String staticGet(){ return "export class staticGet()"; } public String dynamicGet(){ return "export class dynamicGet()"; } public static void main(String[] args){ Super sup = new Sub(); //向上转型 System.out.println(sup.staticGet()); System.out.println(sup.dynamicGet()); } } 输出: base class staticGet() export class dynamicGet()有输出结果可以看出,静态方法不具有多态性,静态方法是与类,而非单个对象相关联的。
相关文章推荐
- Java基础学习总结——Java对象的序列化和反序列化
- java注释说明
- Java生成一个UTF-8文件
- Spring4 MVC json问题(406 Not Acceptable)
- spring----contextConfigLocation
- Java DFA算法实现敏感词过滤
- java并发编程学习:如何等待多个线程执行完成后再继续后续处理(synchronized、join、FutureTask、CyclicBarrier)
- java08:成绩管理系统
- Java抽象类和接口的区别
- java实例变量初始化
- Protobuf在Java中的使用
- Java制作证书的工具keytool用法总结
- java jdbc连接数据库的完整步骤
- Maven .m2\repository\jdk\tools\1.7 missing
- Java对象的序列化和反序列化
- 常用java代理方法
- java Junit 测试
- Eclipse配色
- test9.10
- 版本问题 Java:Unsupported major.minor version 51.0 (unable to load class . . .