1, 类的继承
ABAP 所有的类都是默认继承了系统中的空类 OBJECT.
具有一般性的类称为基类(Superclass), 其各个子类称为派生类(Subclass).
在类定义时, 使用 INHERTING FROM 附加项可以指定派生类和基类之间的继承关系.
1 2 3 |
CLASS c2 DEFINITION INHERITING FROM c1. ... ENDCLASS. |
ABAP 中的继承为单一继承, 即一个类可以有多个派生类, 但只能有一个直接基类.
在继承过程中各成员的组件可见性如下:
- 一个派生类中的公有成员包括其本身公有部分定义的成员以及所有基类公有成员, 这些公有成员可以通过选择运算符 "->" 在类外部获得.
- 一个派生类中的被保护成员包括其本身被保护部分定义的成员以及所有基类的被保护成员. 这些成员不能通过组件选择运算符 "->" 在类外部获得, 但可以在派生类内部使用. 在类外部看, 其行为与类私有成员完全一致.
- 一个派生类中的私有成员只包括其本身私有部分定义的成员. 这些成员只能在派生类内部使用.
因而, 继承类和基类的公有成员和被保护成员享有共同的命名空间, 而私有成员则在不同类之间可以出现重名情况.
参照基类声明的引用变量可以指向其继承类的对象, 如上图所示, 对象 n 是类 Class3的一个实例, 而左侧的三个引用变量 CREF1, CREF2, CREF3 则分别参数类 Class1, Class2, Class3 生成. 这三个类存在继承关系. 参考基类声明的引用变量也可以指向其派生类, 即三个变量均可以指向对象 n, 但要注意的是 CREF1 只能访问 Class1 的公有组件, 而 CREF2 可以访问 Class1 和 Class2的公有组件, CREF3 则可以访问全部类的公有组件.
但特别要注意的是: 尽管基类引用变量可以指向其继承类对象, 然而反之则被视为错误的类型转换.
2, 类的多态
多态性的继承实现.
在继承中, 多态性是通过方法重载及引用变量实现的, 即子类可以重新定义并以不同的方式实现基类中的公有或保护方法, 此时基类中的方法需为实例方法.
在派生类中要这样声明:
1 |
METHOD meth REDEFINITION. |
该方法必须和基类中的方法具有相同的接口, 但可以通过不同的代码实现.
在方法重载过程中, 如果在派生类内部仍然需要使用基类中的方法, 则可以使用 SUPER 关键字来指定其基类.
1 |
CALL METHOD super->meth. |
3, 例子代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
REPORT ztest_oo_inherit_2. CLASS base_class DEFINITION ABSTRACT. "抽象类关键字abstract。这里作为基类 PUBLIC SECTION. METHODS: mess ABSTRACT "声明抽象方法,关键字abstract IMPORTING msg TYPE string OPTIONAL. "抽象类可以包含静态成员,class-data,class-methods,class-events "抽象类可以包含非抽象方法. "抽象类可以不定义任何方法。 "抽象类不可以用creat object创建实例。 "但是可以用data obj type ref to 创建抽象类的引用,并接受子类的实例。 ENDCLASS. CLASS base_class IMPLEMENTATION. "抽象类如果不包含非抽象方法,那么可以没有implementation部分。 ENDCLASS . CLASS super_class DEFINITION INHERITING FROM base_class. "继承,关键字inheriting from PUBLIC SECTION. " 重定义父类的方法,关键字redefinition METHODS: mess REDEFINITION. " 关于final方法: " final类中的所有方法都自动识别为final方法。 " 注意: final类中不可以定义abstract方法; " final方法不能是abstract的。(因为那样毫无意义)。 " 而非final类中可以用final关键字声明final方法。 " 对于非final类,其final方法仍会被子类继承,但不可以被子类重写。如下: " METHODS: mess final REDEFINITION. " 父类中有mess,用final redefinition " METHODs: mess3 FINAL. "父类中没有mess3,用final ENDCLASS. CLASS super_class IMPLEMENTATION. "实现方法。注意:方法中不能修改importing形参的值 METHOD mess. WRITE: msg. ENDMETHOD. ENDCLASS. " 关于final类: " final类,即最终类,关键字final,不可以再被继承(这点与final方法不同) " final类可以是抽象类,这种情况下只能使用它的静态组件。 CLASS final_class DEFINITION FINAL INHERITING FROM super_class. PUBLIC SECTION. METHODS: mess REDEFINITION, mess2 IMPORTING msg TYPE string. ENDCLASS. CLASS final_class IMPLEMENTATION . " 通过super调用父类的方法. " 但是super->只能调用当前方法在父类中的版本。 METHOD mess. CALL METHOD super->mess EXPORTING msg = msg. ENDMETHOD. " me->调用当前类中的其它方法 " 最好不要在当前方法中用me->调用这个方法自身, " 否则会造成满溢dump(无止境的自调用) METHOD mess2. CALL METHOD me->mess EXPORTING msg = msg. ENDMETHOD. ENDCLASS. START-OF-SELECTION. DATA obj TYPE REF TO base_class. "创建基类的引用 DATA obj0 TYPE REF TO final_class. "创建子类的引用 CREATE OBJECT obj0. "创建子类的实例 "把子类的实例赋给基类(或父类)的引用 —— 多态性的体现 obj = obj0. "注意,这种情况下,obj将只能调用obj0从obj继承来的成员。 "通过基类的引用,调用子类实例的方法 —— 多态性的体现 CALL METHOD obj->mess EXPORTING msg = '继承和多·子类方法中通过super->调用父类方法的实现'. ULINE. " OO方法的动态调用:用字符串meth容纳方法名,并用圆括号解释方法名: " ObjRef->(meth),或 Class=>(meth) DATA meth TYPE string. meth = 'MESS2'. "这里的字母要大写。 CALL METHOD obj0->(meth) EXPORTING msg = '通过me->调用当前类中的其它方法'. " 静态方法一般不能被子类重写,唯一的例外是静态构造方法。 " 关于super: 只存在super->,不存在super=> " 多态,是指属性或方法在子类中表现为不同形态。多态包括两种类型: " 静态多态性: " 主要指同一类中同名方法的重载. " (ABAP语言目前不支持方法的重载。) " 动态多态性: " 子类对父类方法进行重写; " 程序中用父类(或接口)引用去指向子类的具体实例。 " 程序代码在编译时还不能确定调用的是父类还是子类的方法, " 多态意味着使用同样的接口却实现了不同的操作,这是依靠继承的功能和动态的引用来实现的。 |
运行结果:
以上。
发表评论