是否有办法从ABAP中最嵌套的循环中继续最外层的循环?
Java示例。在这种语言中有一个使用标签的结构(大多数人都不知道),它允许我从嵌套的循环中继续最外层的循环。
public class NestedLoopContinue {
public static void main(String[] args) {
label1: for (int i = 0; i < 5; i++) {
for (int j = 0; j < 2; j++) {
if (i == 3) {
continue label1;
}
}
System.out.println(i + 1);
}
}
}
这个输出1
2
3
5
现在,我如何用一种聪明的方式在ABAP中做到这一点呢?一个解决方案是使用TRY. ENDTRY.
块,但它是一个黑客。还有其他想法吗?
DATA: l_outer_counter TYPE i.
DO 5 TIMES.
l_outer_counter = sy-index.
TRY.
DO 2 TIMES.
IF l_outer_counter = 4.
RAISE EXCEPTION TYPE cx_abap_random.
ENDIF.
ENDDO.
WRITE / l_outer_counter.
CATCH cx_abap_random.
CONTINUE.
ENDTRY.
ENDDO.
或者可能有一种方法来判断DO. ENDO.
是否以EXIT
语句结束(当然不引入自己的变量,如SYST
全局变量)?
DATA: l_outer_counter TYPE i.
DO 5 TIMES.
l_outer_counter = sy-index.
DO 2 TIMES.
IF l_outer_counter = 4.
EXIT.
ENDIF.
ENDDO.
IF sy-last_loop_ended_with_exit = abap_true. "???
CONTINUE.
ENDIF.
WRITE / l_outer_counter.
ENDDO.
我不知道abap特定的解决方案,但我以前使用过通用编程解决方案来处理这个问题;只需使用一个布尔值,并在内循环结束时检查是否继续。
Java:public class NestedLoopContinue
{
public static void main(String[] args)
{
for (int i = 0; i < 5; i++)
{
boolean earlyBreak = false;
for (int j = 0; j < 2; j++)
{
if (i == 3)
{
earlyBreak = true;
break;
}
}
if (earlyBreak)
{
continue;
}
System.out.println(i + 1);
}
}
}
在ABAP中:
DATA: l_outer_counter type i,
early_break type FLAG.
DO 5 TIMES.
l_outer_counter = sy-index.
DO 2 TIMES.
IF l_outer_counter = 4.
early_break = ABAP_TRUE.
EXIT.
ENDIF.
ENDDO.
IF early_break = ABAP_TRUE.
CLEAR early_break.
CONTINUE.
ENDIF.
WRITE / l_outer_counter.
ENDDO.
我读到Java中首先存在基于标签的中断的原因是因为GOTO
语句明确地不存在,而基于标签的中断所涵盖的情况是GOTO
的少数几个"好"用途之一,团队想要维护。
一般来说,这是一个非常尴尬的结构。有没有可能重构你的代码(也许是交换循环的内部属性),从一开始就不需要这个?
在使用嵌套循环时,我经常发现提高可读性的最佳方法,并避免使用更不寻常的方法(例如打破标签,这不仅因为其goto性质而引起争议,而且还降低了可读性,因为很多人不熟悉它们)是将内部循环提取到一个单独的函数中。我不知道这在ABAP中是如何实现的,但重构后的Java等价将是:
public class NestedLoopContinue {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
NestedLoopContinue.innerLoop(i)
}
}
static void innerLoop(int i) {
for (int j = 0; j < 2; j++) {
if (i == 3) {
return;
}
}
System.out.println(i + 1);
}
}
我认为在这个例子中,这实际上变得更不容易读,因为很难在两个方法之间遵循逻辑。然而,如果这是一个真实世界的例子(其中的方法和变量具有一些实际含义和相应的名称),那么将内部循环提取到单独的方法中的结果将比使用标签更具可读性。
根据robjohncox的回答,ABAP代码可能是这样的:
CLASS lcl_nested_loop_continue DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS:
main.
PRIVATE SECTION.
CLASS-METHODS:
inner_loop
IMPORTING
i_index TYPE i.
ENDCLASS.
CLASS lcl_nested_loop_continue IMPLEMENTATION.
METHOD main.
DO 5 TIMES.
lcl_nested_loop_continue=>inner_loop( sy-index ).
ENDDO.
ENDMETHOD.
METHOD inner_loop.
DO 2 TIMES.
IF i_index = 4.
RETURN.
ENDIF.
ENDDO.
WRITE / i_index.
ENDMETHOD.
ENDCLASS.