The normal goal in object-oriented programming is for your code to manipulate references to the base type.(面向对象编程中的基本目的是:让代码只操纵对基类的引用)——引自Thinking in java
如果有一天,当你发现编程对你来说变得愈发简单时,回头看一看你写过的代码,你会恍然大悟——原来多态无处不在。书中常说,面向基类(接口)的编程使代码更容易写、更容易读、更容易维护,设计上也更容易实现、理解和改变。我觉得这不是重点,重要的是这些特性会让你越来越喜欢他,而当你越来越喜欢它的时候,你所感受到的那种快乐已经远远超过了这些优点所带来的快感。
直入正题,为了进一步的了解多态,我们应该先了解一下动态绑定(Dynamic Binding)与静态绑定(Static Binding)。
一、动态绑定与静态绑定
1、动态绑定
动态绑定是指,在执行期间判断所引用对象的实际类型,根据其实际类型调用其方法。动态绑定又名后期绑定(Late Binding),可以这样理解动态绑定,在编译期无法解析调用的方法,只有在运行时才能正确解析。如下示例。
class SuperClass {
public void doSomething(){
System.out.println("SuperClass.doSomething");
}
}
class SubClass extends SuperClass{
public void doSomething(){
System.out.println("SubClass.doSomething");
}
}
public class Test {
public static void main(String[] args){
SuperClass sup = new SuperClass();
SuperClass sub = new SubClass();
sup.doSomething();
sub.doSomething();
}
}
Output:
SuperClass.doSomething
SubClass.doSomething
可以看到,在编译阶段无论是sup还是sub都是Super的引用,而在运行时,它们各自指向了SuperClass和SubClass。因此,我们可以看到,在Java中动态绑定绑定的方法是基于实际的对象类型的,而不是声明时对象的引用类型。(注:这些方法通常是可以被重写的派生方法,因此编译期无法去识别方法的版本)
2、静态绑定
能被编译器在编译期解析的绑定称为静态绑定或早期绑定(Early Binding)。所有的实例方法调用都是在运行时进行解析的,而所有的static方法调用都是在编译期完成解析的。由于静态的方法是class的方法,而非对象的方法(当然,对象也可以调用此类方法),因此解析它们只需在编译期就可以了。(静态的方法可以被重写吗?)
同样的,Java中的成员变量也是静态绑定的。Java没有提供成员变量的多态。如下示例。
class SuperClass {
String variable = "the variable of SuperClass";
}
class SubClass extends SuperClass{
String variable = "the variable of SubClass";
}
public class Test {
public static void main(String[] args){
SuperClass sup = new SuperClass();
SuperClass sub = new SubClass();
System.out.println(sup.variable);
System.out.println(sub.variable);
}
}
Output:
the variable of SuperClass
the variable of SuperClass
输出结果相同,说明成员变量在编译器完成了绑定,而非运行时。根据这些线索,我们也可以推测出,private方法也是静态绑定的,因为无法实现它的派生方法。
3、链接
可以说,动态绑定使我们对多态有了更深的认识,当然它的底层实现还有待研究。这里之所以提到多态,是因为多态与RTTI是相辅相成的。所以怎样去理解它们,RTTI是什么,为什么要使用RTTI,等等这些问题还有待解决。
二、多态与RTTI
1、为什么需要RTTI
一个典型的例子,来自Thinking in Java。
import java.util.List;
import java.util.Arrays;
public class Shapes {
public static void main(String[] args){
/**
*1、 当把Shape对象放入List<Shape>的数组时会向上转型。但向上转型为Shape的时候也丢失了Shape对象的具体类型。
*2、 对于数组而言,它们只是Shape类的对象——实际上它将所有的事物都当作Object持有。
*3、 当从数组中取出元素时,这种容器会自动将结果转型回Shape,这是RTTI最基本的使用形式。
*4、 Shape对象执行什么样的代码,是由引用所指向的具体对象Circle、Square或Triangle而决定的(多态)。
*/
List<Shape> shapeList = Arrays.asList(new Circle(),new Square(),new Triangle());
for(Shape shape : shapeList){
shape.draw();
}
}
}
abstract class Shape{
void draw(){System.out.println(this + ".draw()");}
/**
* 如果某个对象出现在字符串表达式中,toString()方法就会被自动调用,以生成表示该对象的String。
*/
abstract public String toString();
}
class Circle extends Shape{
public String toString() {
return "Circle";
}
}
class Square extends Shape{
public String toString() {
return "Square";
}
}
class Triangle extends Shape{
public String toString() {
return "Triangle";
}
}
Output:
Circle.draw()
Square.draw()
Triangle.draw()
在Java中,所有的类型转换都是在运行时进行正确检查的。这也正是RTTI名字的含义:在运行时,识别一个对象的类型。
这个实例用泛型、RTTI和多态共同完成了一项任务,泛型确保类编译器的类型转换;RTTI完成了运行时的类型转换;多态使对应的对象执行了正确的行为。
但是,如果仅仅至于一个对象家族的通用类打交道无法满足我们的需求,我们该怎么办呢?如果我们在运行时能够确定识别一个泛化引用的确切类型,这样我们就能满足我们对特殊问题的需求,那么这个技术点又该如何解决呢?
2、链接
RTTI能够为我们解决上面提到的问题,它能够使我们在运行时查询泛化引用的确切类型。理解RTTI的关键,还需从Class对象入手!
三、Class对象
1、什么是Class对象
每个类都有一个Class对象。Class对象包含了与类有关的信息,它用来创建类的所有的常规对象。
2、Class对象的由来
位于堆区中的Class对象,是类加载的最终产物——类加载器的行为目标。
3、类的加载
类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.class对象,用来封装类的方法区内的数据结构。
1、所有的类都是在对其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员引用时,就会加载这个类。
2、程序在它开始运行之前并非被完全加载,其个部分是在必需时才加载的。(动态加载)
3、类加载器首先检查这个类的Class对象是否已经加载。如果尚未加载,默认的类加载器(System ClassLoader)就会根据类名查找.class文件。
4、一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。
如下示例:
class First{
static { System.out.println("Loading First!"); }
}
class Second{
static {System.out.println("Loading Second!");}
}
class Third{
static {System.out.println("Loading Third!");}
}
public class LoadTest {
//当程序创建第一个对类的静态成员的引用时,就会加载这个类
public static void main(String[] args){
System.out.println("start from main method");
new First();
new First();
new First();
System.out.println("After creating First");
try{
Class.forName("Second");
new Second();
}catch(ClassNotFoundException ep){
System.out.println("Couldn't find Second");
}
System.out.println("After Creating Second");
new Third();
System.out.println("After creating Third");
}
}
Output:
start from main method
Loading First!
After creating First
Loading Second!
After Creating Second
Loading Third!
After creating Third
4、链接
如果要使用一个类,仅仅是加载它是不够的。要使用它,还必需进行链接与初始化。这些仅仅是个开始,如何在运行时确定一个泛化引用的具体类型,如何安全严谨地使用Class对象,都是我们亟待解决的问题。
分享到:
相关推荐
1. JAVA 使用 Class 对象来执行 RTTI(RunTime Type Information),创建这个类的实例。 2. 验证同一个类的多个对象的Class对象是一个。 获取 Class 对象有多种方式: 1. 通过 Class 的 forName(String name) 方法...
实现c++根据类名创建c++ 对象,一个文件简单明了,,,,,
RTTI,全称Runtime Type Information(运行时类型信息),是编程语言中的一种特性,允许程序在运行时获取对象的类型信息。在Delphi中,RTTI是一个强大的工具,它使得开发者能够在运行时检查、操作类的属性、方法和...
在C++编程中,RTTI(Run-Time Type Information,运行时类型信息)是一个强大的特性,它允许程序在运行时检查对象的实际类型。RTTI是C++标准库的一部分,提供了获取对象动态类型信息的能力,这对于多态性和面向对象...
首先,RTTI是C++的一个特性,允许程序在运行时获取对象的实际类型信息。在MFC中,RTTI主要通过`_tclass`宏和`dynamic_cast`关键字来实现。`_tclass`宏用于标识一个类是MFC中的消息映射类,使得类可以参与到MFC的消息...
运行时类型识别(Runtime Type Information,简称RTTI)是C++语言中的一种特性,它允许在程序运行期间获取对象的实际类型信息。RTTI是C++为面向对象编程提供的一项强大工具,尤其在多态性编程中,能够帮助我们实现更...
运行时类型识别(RTTI,Runtime Type Information)是C++编程语言中的一种特性,允许程序在运行时查询对象的实际类型信息。RTTI 提供了一种方法来检查对象的动态类型,这对于多态性编程和处理类层次结构尤其有用。...
在C++编程中,RTTI(Run-Time Type Information,运行时类型信息)是一种特性,它允许程序员在程序运行时查询对象的实际类型。MFC(Microsoft Foundation Classes)是微软提供的一个C++类库,用于构建Windows应用...
C++ 的运行时类型识别 (Run-Time Type Information, RTTI) 是一种强大的特性,允许程序在运行时获取对象的类型信息,这对于支持诸如多态性等功能至关重要。本文将深入探讨 C++ 中的 RTTI 机制,特别是 `dynamic_cast...
运行时类型信息(Runtime Type Information,简称RTTI)是C++语言中的一种特性,它允许在程序运行时查询对象的类型信息。RTTI是C++的多态性的一个重要组成部分,尤其是在面向对象编程中,它提供了强大的动态类型检查...
在C++编程语言中,运行时类型信息(Runtime Type Information,简称RTTI)是一个强大的特性,它允许程序在运行时检查对象的精确类型。当我们有动态类型或者多态性需求时,RTTI就显得尤为重要。在给定的场景中,“c++...
1. **获取类型信息**:首先,你可以使用`TRttiContext.Create`创建一个RTTI上下文,然后通过`TRttiContext.GetType`方法传入一个类名或`TClass`实例来获取对应的`TRttiType`对象,该对象包含了类型的所有信息。...
RTTI是编程语言中的一项特性,允许在运行时获取对象的类型信息。这在动态类型检查和反射中非常有用。例如,在Delphi或C++Builder等环境中,RTTI可以用来获取类的成员信息,包括方法、属性和字段,甚至可以在运行时...
RTTI,全称为Run-Time Type Information,是C++语言中的一种特性,允许程序在运行时获取对象的实际类型信息。这在多态编程中尤其有用,因为它使得动态绑定和类型检查成为可能,增强了代码的灵活性和安全性。下面我们...
Delphi的运行时类型信息(Runtime Type Information,简称RTTI)是其强大的特性之一,它允许程序员在程序运行时获取对象或类的类型信息。在Delphi中,RTTI可以帮助我们进行动态类型检查、反射操作以及自动生成代码等...
在编程领域,特别是使用Delphi这种面向对象的编程语言时,`RTTI`(Run-Time Type Information)是一项非常重要的特性。RTTI允许程序在运行时获取类型信息,这对于动态操作对象、实现反射、代码生成以及元编程等高级...
这两种运算符内部都是通过RTTI来实现的,利用`TObject.ClassType`和`TObject.ClassInfo`等属性来获取对象的实际类型,并进行相应的类型检查或转换操作。 #### TTypeInfo – RTTI 信息的结构 `TTypeInfo` 是一个...
C++的运行时类型信息(Runtime Type Information,简称RTTI)是一种强大的特性,它允许在程序运行时查询对象的实际类型。在深入探讨RTTI的实现机制之前,我们首先理解RTTI的基本概念。在C++中,类型识别分为静态识别...
在C++编程语言中,Run-Time Type Information(RTTI)是一项关键特性,它允许程序员在程序运行时查询对象的确切类型。RTTI是C++多态性的重要组成部分,特别是对于动态类型检查和类型转换非常有用。本文将深入探讨...