键入通用的接口方法参数以使接口更易于访问的优点和缺点是什么?
What are the pros and cons of typing interface method parameters generic to make the interface more accessible?
我有一个应用程序使用许多不同的简单转换从 abap 结构创建 xml 字符串,因此使用许多不同的 abap 结构。
我想使用更灵活的 OO 方法和接口来执行此操作,但由于结构不同,方法签名导入参数总是不同的。
改为键入导入参数 generic 的优点和缺点是什么,这样我就可以在每个 class 中从一个接口实现一种方法来处理不同的转换?
INTERFACE if_transformer.
METHODS transform_xml
IMPORTING isource_structure TYPE REF TO data
RETURNING VALUE(rxml_string) TYPE string.
ENDINTERFACE.
...
CLASS material_transformer definition.
PUBLIC SECTION.
INTERFACES if_transformer.
ENDCLASS.
CLASS material_transformer IMPLEMENTATION.
METHOD if_transformer~transform_xml.
FIELD-SYMBOLS <structure> TYPE concrete_structure.
ASSIGN isource_structure->* TO <structure>.
...
ENDMETHOD.
ENDCLASS.
你的类型越具体,你就越早发现错误,你的接口就越容易被理解,你在验证和casting/converting你想要处理的具体类型方面的开销就越少。
例如,假设您将方法 add_number
键入为 methods add_number importing n type i
。然后编译器将拒绝错误的语句 add_number( 'xyz' )
并且这个 class 的错误永远不会变成可执行代码。反过来,任何阅读该方法声明的人都可以很容易地看出该方法只接受整数,不接受浮点数,不接受压缩,并且绝对不接受包含数字的字符串。在该方法中,您可能可以直接获取输入 n
并对其执行某些操作,例如 result = sum_so_far + n
,而无需首先验证输入或将其转换为其他内容。
相比之下,假设您键入与 methods add_number importing n type ref to data
相同的方法 add_number
。编译器会很乐意接受 add_number( ref #( 'xyz' ) )
,尽管这完全是胡说八道;因此,这个 class 错误只会在运行时被检测到,类型转换异常是围绕此的代码必须以有意义的方式做出反应的。阅读该方法声明的人必须查阅它的文档、单元测试、and/or 代码以找出它接受的输入类型;没有办法仅从规范中猜测它。最后,在方法内部,首先要对输入进行验证和转换,然后才能对其进行处理,例如is_integer( n )
、cast
、assign
等;如果输入不可接受,则需要找到合适的错误处理机制,例如抛出良好的异常。
对于像 JavaScript 这样的软类型语言,默认使用通用类型。然而,历史表明人们通常更喜欢更强的类型,至少在服务器端是这样,这导致了 TypeScript 或 Deno 等后续演进。对于像 ABAP 这样的强类型语言,经验法则是选择尽可能精确的数据类型。
请注意,泛型类型有多个放宽级别。例如,在求助于最大泛型类型 data
之前,您应该考虑求助于“部分”泛型类型,例如接受 ABAP 结构的 simple
或接受表的 standard table
。
Florian 的出色回答。我可能会补充说,我在类似情况下使用的一种方法是使用工厂 class 检查输入数据并实例化适当的 class 来处理它。
我有一个应用程序使用许多不同的简单转换从 abap 结构创建 xml 字符串,因此使用许多不同的 abap 结构。
我想使用更灵活的 OO 方法和接口来执行此操作,但由于结构不同,方法签名导入参数总是不同的。
改为键入导入参数 generic 的优点和缺点是什么,这样我就可以在每个 class 中从一个接口实现一种方法来处理不同的转换?
INTERFACE if_transformer.
METHODS transform_xml
IMPORTING isource_structure TYPE REF TO data
RETURNING VALUE(rxml_string) TYPE string.
ENDINTERFACE.
...
CLASS material_transformer definition.
PUBLIC SECTION.
INTERFACES if_transformer.
ENDCLASS.
CLASS material_transformer IMPLEMENTATION.
METHOD if_transformer~transform_xml.
FIELD-SYMBOLS <structure> TYPE concrete_structure.
ASSIGN isource_structure->* TO <structure>.
...
ENDMETHOD.
ENDCLASS.
你的类型越具体,你就越早发现错误,你的接口就越容易被理解,你在验证和casting/converting你想要处理的具体类型方面的开销就越少。
例如,假设您将方法 add_number
键入为 methods add_number importing n type i
。然后编译器将拒绝错误的语句 add_number( 'xyz' )
并且这个 class 的错误永远不会变成可执行代码。反过来,任何阅读该方法声明的人都可以很容易地看出该方法只接受整数,不接受浮点数,不接受压缩,并且绝对不接受包含数字的字符串。在该方法中,您可能可以直接获取输入 n
并对其执行某些操作,例如 result = sum_so_far + n
,而无需首先验证输入或将其转换为其他内容。
相比之下,假设您键入与 methods add_number importing n type ref to data
相同的方法 add_number
。编译器会很乐意接受 add_number( ref #( 'xyz' ) )
,尽管这完全是胡说八道;因此,这个 class 错误只会在运行时被检测到,类型转换异常是围绕此的代码必须以有意义的方式做出反应的。阅读该方法声明的人必须查阅它的文档、单元测试、and/or 代码以找出它接受的输入类型;没有办法仅从规范中猜测它。最后,在方法内部,首先要对输入进行验证和转换,然后才能对其进行处理,例如is_integer( n )
、cast
、assign
等;如果输入不可接受,则需要找到合适的错误处理机制,例如抛出良好的异常。
对于像 JavaScript 这样的软类型语言,默认使用通用类型。然而,历史表明人们通常更喜欢更强的类型,至少在服务器端是这样,这导致了 TypeScript 或 Deno 等后续演进。对于像 ABAP 这样的强类型语言,经验法则是选择尽可能精确的数据类型。
请注意,泛型类型有多个放宽级别。例如,在求助于最大泛型类型 data
之前,您应该考虑求助于“部分”泛型类型,例如接受 ABAP 结构的 simple
或接受表的 standard table
。
Florian 的出色回答。我可能会补充说,我在类似情况下使用的一种方法是使用工厂 class 检查输入数据并实例化适当的 class 来处理它。