我们都在争论何时使用静态方法或实例方法。在大多数情况下,我们会采用最简单的方法,但这可能不是正确的方法。让我们尝试探索并确定在确定“静态”或“实例”时最好的方法是什么。
基本
在跳入差异和应该使用之前,请先检查一下静态方法和实例方法的基础。
静态方法
静态方法是可以与类实例无关地调用的方法。您只能在Static方法中访问静态属性和静态事件。
这是您声明和调用静态方法的方式:
* static method declaration
CLASS lcl_data DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:
get_data IMPORTING iv_date TYPE d.
ENDCLASS. "lcl_data DEFINITION
*
* static method call - calling using class name
lcl_data=>get_data( '20130313' ).
*
CLASS lcl_data IMPLEMENTATION.
METHOD get_data.
* do something
ENDMETHOD. "get_Data
ENDCLASS. "lcl_data IMPLEMENTATION
实例方法
实例方法是只能使用对象引用调用的方法。实例方法可以访问实例属性和实例事件。
这是您声明和调用实例方法的方式:
*Instance method declaration
CLASS lcl_data DEFINITION.
PUBLIC SECTION.
METHODS:
get_data IMPORTING iv_date TYPE d.
ENDCLASS. "lcl_data DEFINITION
*
* Instance method call - calling using the object reference
DATA: lo_data TYPE REF TO lcl_data.
CREATE OBJECT lo_data.
lo_data->get_data( '20130313' ).
*
CLASS lcl_data IMPLEMENTATION.
METHOD get_data.
" get data
ENDMETHOD. "get_data
ENDCLASS. "lcl_data IMPLEMENTATION
为什么不使用静态方法
从示例代码中可以看到,创建静态方法听起来不错,而且很有利可图,因为在调用方法时不涉及冗长的步骤-声明引用变量,实例化对象和调用方法。无需执行这些步骤即可直接调用静态方法。但是使用静态的设计不会像听起来那样好。让我告诉你为什么:
静态方法无法重新定义
面向对象编程的最重要方面之一是多态性–只要需要,就用更具体的实现替换默认实现。在OO ABAP中,使用方法重新定义可实现多态性。正如我们在前面的文章Override Static method中讨论的那样,我们无法重新定义Static方法。造成这种情况的主要原因是静态方法可以独立运行。使用静态方法,可以通过显式指定定义它们的类型来调用它们。这意味着,您可以直接调用实现,而该实现不绑定到实例对象的任何特定实现。
让我们通过一个简单的场景来了解这一点–如果您有使用BAPI进行销售订单创建的静态方法。在设计时,此方法仅用于一种业务场景。现在,您想将此用于不同的业务场景。在这种新方案中,您需要在项目上设置一些其他字段,例如“更高级别”项目,确定新项目类别等。您认为简单的解决方案是在方法中添加一个代码块来执行此逻辑XYZ销售区域,ZABC订单类型。您在这里所做的事情是打开一个框,您将在其中继续添加越来越多的条件。因此违反了单一责任原则。
如果您具有Instance方法,则可以轻松继承另一个类,重新定义该方法并替换现有的实现。在这个新的实现中,您将设置其他字段并调用Super Method来完成其余的工作。
ABAP单元测试中的问题
我尚未涵盖ABAP单位。他们即将来临…
测试治具
在ABAP单位中,可以使用称为测试夹具的特殊方法设置测试数据。使用此方法后,将在您有权访问测试数据的地方调用您的测试方法。由于每个ABAP单元测试都应该可以单独进行操作和测试,因此静态方法很难进行测试。静态方法将使用静态属性,并且由于它们正在使用静态属性,因此您必须在测试治具方法中始终具有其他逻辑来摆脱它们。
如果您正在使用实例的对象,则可以轻松清除它。当实例化一个新对象时,旧对象将被取消引用而无需任何其他逻辑
建设者
与实例方法的CONSTRUCTOR方法相反,使用静态方法的设计最终将使用CLASS_CONSTRUCTOR。如前所述,CLASS_CONSTRUCTOR和CONSTRUCTOR:谁在谁之前?,很难预测何时调用CLASS_CONSTRUCTOR。首次访问该类时可以调用CLASS_CONSTRUCTOR,即使已访问该类以获得常量值也是如此。这使其无法操作且无法测试。
在同一会话中重用该实用程序
静态属性将绑定到内存,直到会话结束。这意味着,如果仅设置一次值,则在会话结束之前不会清除它们。如果是静态属性,则不可能在同一会话中利用相同的逻辑。例如,一个简单的实用程序类,用于生成应用程序日志。
设计就像:
在静态类的属性中收集日志
收集后调用静态方法以生成应用程序日志。
该设计似乎完全适合应为静态的实用程序类。但这是一个问题,它限制了您在同一会话中再次使用相同的逻辑而不会丢失现有信息。可以说,您正在使用此应用程序日志收集错误。现在,在同一程序中,您将不会生成另一个应用程序日志来跟踪执行的活动。由于您已收集了静态属性中的所有错误,因此除非将其复制到另一个占位符并调用Utility类以生成跟踪日志,否则当您尝试使用同一Utility类时,您将丢失错误日志数据。
另一方面,您使用实例方法和属性进行了设计,则可以简单地创建另一个实例并开始使用它来跟踪日志。
拇指法则
因此,基于所有这些事实,我们可以得出以下经验法则:
让我知道是否要添加使用或不使用静态方法的其他观点。