If-Else VS Chuyển cuối dòng


8

Tôi đã tự hỏi nếu lệnh if-else, giống như một câu lệnh switch mà không có lệnh break.

if( boolean_expression_1 )
  statement_1
else if( boolean_expression_2 )
  statement_2
else 
  default_statement

Giống như:

switch( controlling_expression )
{
case: ( boolean_expression_1 )
{
     statement_1
     break;
}
case: ( boolean_expression_2 )
{
     statement_2
     break;
}
default:
{
     default_statement
}

Thay đổi câu hỏi thành những gì tôi thực sự có ý nghĩa, MÀ LÀ OPPOSITE của những gì tôi đã hỏi một cách rõ ràng. Chỉnh sửa ví dụ để phù hợp với câu hỏi dự định. Tôi biết một số bạn đã tự hỏi liệu hai câu nói có vẻ giống nhau hay không, và những câu khác trả lời liệu chúng có giống nhau theo nghĩa đen không . Tôi đánh giá cao cả hai, vì nó mang đến một góc độ của những sự tương đồng đã được định trước và cả những gì chúng (khác nhau / giống nhau) sâu thẳm
Chris Okyen

Nếu bạn thấy các loại cấu trúc này thú vị, tôi khuyên bạn nên xem qua mô hình phù hợp với các điều kiện và bảo vệ. Các khái niệm rất giống nhau nhưng có thể biểu cảm tuyệt vời. Tôi quen thuộc với họ trong F # nhưng trên JVM, tôi tin Scala hỗ trợ họ.
Steven Evers

Câu trả lời:


6

Tôi đã tự hỏi nếu câu lệnh if-other, giống như một câu lệnh switch không có câu lệnh break.

Đó là ngược. Loại.

Một chuỗi if, if if, ... khác trong đó tất cả các phép thử đều là các phép thử đẳng thức đơn giản trên cùng một biến của biểu mẫu (variable == value)hoặc ((variable == value1) || (variable == value2) ...)có thể được chuyển đổi thành câu lệnh chuyển đổi trên biến đó. Các (variable == value)xét nghiệm trở thành case value:, và cơ thể của if(hoặc else if) trở thành cơ thể của vụ án, nhưng bạn cần thêm một breaktuyên bố vào cuối vụ án. Các ((variable == value1) || (variable == value2) ...)thử nghiệm trở thành một chuỗi các trường hợp có dạng case value1: case value2: ... case valuen:An nếu chuỗi có các thử nghiệm phức tạp hơn nói chung khác với một câu lệnh chuyển đổi.

Nếu mọi trường hợp trong câu lệnh chuyển đổi kết thúc break, câu lệnh chuyển đổi đó luôn có thể được viết lại thành một chuỗi if, khác if, .... Việc chuyển đổi từ chuyển sang một chuỗi if cũng có thể xảy ra khi rơi qua bị giới hạn ở những thứ như case A: case B: ... case N: do_something(); break;Rơi qua trong đó một cơ thể không trống rơi vào một cơ thể không trống khác không thể chuyển đổi trực tiếp thành một chuỗi if.


Cảm ơn. Các câu lệnh if-other là các câu lệnh percpered / dường như chuyển đổi (...) với một dấu ngắt ở mỗi đầu của mỗi thân máy. Nhiều câu lệnh if một mình mà không có cặp khác , là các câu lệnh được chuyển / dường như chuyển đổi (...) không có dấu ngắt ở cuối mỗi trường hợp. Tôi sẽ mô tả làm thế nào nó được giải thích, thêm các chi tiết về lồng nhau, nhưng điều đó nằm ngoài phạm vi / nhiều hơn để nhai cho phần của câu hỏi này.
Chris Okyen

3

Mặc dù suy nghĩ về một khối if-if giống như một câu lệnh chuyển đổi mà không nghỉ có thể là một sự trừu tượng hữu ích cho một lập trình viên mới, nó không phải là một so sánh hoàn hảo.

Switch có lẽ liên quan chặt chẽ hơn với "goto". Cấp, Java không có Goto, nhưng ngôn ngữ được xây dựng dựa trên ý tưởng từ các ngôn ngữ khác như C đã làm. Các nhãn "trường hợp" và "mặc định" không thực sự khác biệt so với bất kỳ mục tiêu nhảy nào khác cho câu lệnh goto, vì vậy hành vi dự kiến ​​sẽ là tiếp tục thực thi dòng mã tiếp theo trong khối (toàn bộ câu lệnh chuyển đổi là khối) . Điều này được giải thích thêm trong một trong những câu trả lời cho một câu hỏi liên quan: Tại sao chúng ta phải sử dụng break in switch? Vì vậy, chúng tôi kết thúc với trường hợp bạn cần một tuyên bố nghỉ để nói với chương trình của bạn rằng bạn đã thực hiện xong khối này. Bạn có thể sử dụng break trong các loại câu lệnh khác như vòng lặp for hoặc while tương tự.

Trong các ngôn ngữ như java sử dụng ngắn mạch, trong khối if-otherif-other, nếu điều kiện cho trường hợp đầu tiên của câu lệnh if là đúng, thì các điều kiện khối if và khác sẽ không được đánh giá. Sau một dự kiến, bạn sẽ tìm thấy một khối mã được đặt trong dấu ngoặc nhọn {} hoặc một câu lệnh. Theo định nghĩa, khác có nghĩa là "khác" hoặc điều kiện trước đó là không đúng, sẽ có một chút mâu thuẫn khi để mã rơi qua.


"Mặc dù suy nghĩ về một khối 'nếu-khác' giống như một 'tuyên bố chuyển đổi' mà không nghỉ ngơi có thể là một sự trừu tượng hữu ích cho một lập trình viên mới, nhưng đó không phải là một so sánh hoàn hảo." - Không phải bạn có nghĩa là "nghĩ về một khối 'nếu-khác' giống như một 'tuyên bố chuyển đổi' khi nghỉ ...?"
Chris Okyen

Mâu thuẫn là đúng!
Chris Okyen

1

Ngôn ngữ lập trình thường cung cấp nhiều cấu trúc khác nhau cho phép bạn thể hiện logic tương tự bằng cách sử dụng cú pháp khác nhau.

if/ elsecâu lệnh không "rơi vào" nhau vô điều kiện; các khác từ khóa ngăn chặn bất kỳ thêm else-ifđiều kiện được đánh giá giống như một breakở phần cuối của một trường hợp khối được bạn ra khỏi một công tắc, tuy nhiên việc tạo ra một tập hợp các độc ifs (không sử dụng else) sẽ làm cho mỗi ifđiều kiện để được đánh giá ngày của riêng mình.

Coversely, loại bỏ các breaktừ khóa từ ngày kết thúc của bạn casekhối sẽ làm cho luồng thực hiện để vô điều kiện tiếp tục giảm qua đối với trường hợp tiếp theo cho đến khi một trong hai nghỉ ngơi / khứ hồi / goto bắt gặp hoặc sự kết thúc của khối chuyển đổi đã đạt được.

Có những trường hợp (hiếm khi) trong đó chuyển đổi trường hợp chuyển đổi được coi là hữu ích; tuy nhiên, nó phổ biến hơn và thường là thành ngữ hơn khi muốn mỗi khối trường hợp được xử lý riêng.

if-elseswitch-caselà cả hai cấu trúc cho phép bạn thể hiện lựa chọn (ra quyết định) bằng ngôn ngữ lập trình; đôi khi sự lựa chọn giữa hai là xuống phong cách cá nhân, lần khác có những lý do thuyết phục để lựa chọn một trong khác - Một sự lựa chọn tương tự tồn tại khi lựa chọn cho chuyến trong khi bày tỏ sự lặp lại.


Cảm ơn. Một ví dụ về tình huống trong trường hợp chuyển đổi được coi là hữu ích là khi bạn muốn một trường hợp làm điều gì đó và có thể cho phép điều gì đó xảy ra sau khi kết quả đúng cho trường hợp đó nếu trường hợp tiếp theo cũng đúng ... trường hợp chuyển đổi (i): A {break; } case: B {....} case: C {.... break} Vì vậy, nếu B xảy ra và sau đó cho phép khả năng C xảy ra ...
Chris Okyen

0

Câu trả lời là không - câu lệnh if không giống như câu lệnh switch mà không ngắt. Hãy để chúng tôi bắt đầu với phần này của câu hỏi của bạn:

nếu boolean_expression_1 là đúng, nó sẽ kiểm tra xem boolean_expression_2 có đúng không?

Chúng ta có thể tìm thấy câu trả lời với chương trình này. Thủ thuật là, chúng ta gọi một phương thức là boolean_expression của chúng ta và sử dụng System.out.println () để xem, nếu phương thức được thực thi. Bằng cách này, chúng tôi biết nếu biểu thức đã được đánh giá. Đây là chương trình:

public class IfElseExample {

    private static boolean booleanExpression1() {
        System.out.println("Expression 1 is being evaluated.");
        return true;
    }

    private static boolean booleanExpression2() {
        System.out.println("Expression 2 is being evaluated.");
        return true;
    }

    public static void main(String[] args) {
        if (booleanExpression1()) 
            System.out.println("Statement 1 is executed");
        else if (booleanExpression2()) 
            System.out.println("Statement 2 is executed");
        else
            System.out.println("Default statement is executed");
    }

}

Bạn sẽ thấy rằng biểu thức boolean thứ hai không được đánh giá. Hành vi này có thể trở nên dễ hiểu hơn nếu bạn đặt trong một số dấu ngoặc (đó là một thói quen tốt trong hầu hết các trường hợp):

    if (booleanExpression1()) { 
        System.out.println("Statement 1 is executed");
    } else {
        if (booleanExpression2()) {
            System.out.println("Statement 2 is executed");
        } else {
            System.out.println("Default statement is executed");
        }
    }

Đây là cách, trình biên dịch xem if-chain gốc của bạn. Như bạn có thể thấy bây giờ, "if" thứ hai là một câu lệnh riêng của nó và như vậy nó không cùng cấp với câu lệnh if đầu tiên. Nếu bạn xâu chuỗi các câu lệnh if nhiều hơn, chúng sẽ được lồng sâu hơn nữa.

Bạn cũng hỏi, tại sao câu lệnh switch cần một câu lệnh break. Điều này là do câu lệnh switch không được triển khai bên trong với một chuỗi câu lệnh if (cũng không phải là câu lệnh if dựa trên câu lệnh switch). Bạn có thể mong đợi rằng

        switch(controllingExpression()) {
            case 42: System.out.println("A");
                        case 43: System.out.println("B");
            default : System.out.println("z");
        }

được dịch bởi trình biên dịch thành một cái gì đó như:

if (controllingExpression() == 42) {
    System.out.println("A");
} else if (controllingExpression() == 43) {
    System.out.println("B");
} else {
    System.out.println("z");
}

Đây không phải là trường hợp. Thay vào đó, nó sử dụng một câu lệnh bỏ qua ẩn:

int x = numberOfStatementsToSkipFor(controllingExpression());
skip x // hidden skip the next x statements byte code instruction
System.out.println("A");
System.out.println("B");
System.out.println("z");

Phương thức numberOfStatementsToSkipFor () trả về 0 cho 42, 1 cho 43 và 2 cho mọi thứ khác. Bây giờ nó trở nên rõ ràng tại sao chương trình này có thể sản xuất

A
B
z

hoặc là

B
z

hoặc chỉ

z

nhưng không bao giờ

A
B

không có 'z'. Nhưng rõ ràng sẽ tốt nếu chúng ta có thể làm điều này. Và chúng ta có thể bằng cách sử dụng break mà được dịch sang một câu lệnh bỏ qua khác. Vì vậy, nếu bạn đặt break vào tất cả các trường hợp chi nhánh

switch(controllingExpression()) {
    case 42: {
        System.out.println("A");
        break;
    }
    case 43: {
        System.out.println("B");
        break;
    }
    default : System.out.println("z");
}

trình biên dịch sẽ tạo ra điều này:

int x = numberOfStatementsToSkip(controllingExpression());
skip x; // hidden skip the next x statements byte code instruction
System.out.println("A");
skip 3; //"B" + skip + "z"
System.out.println("B");
skip 1;
System.out.println("z");

Cảm ơn tôi đã hiểu mọi thứ cho đến 'int x = numberOfStatementsToSkipFor (controlExpression ());' đoạn mã mô tả cách nó sẽ bỏ qua số x hướng dẫn mã byte tiếp theo nếu bạn có câu lệnh chuyển đổi như bạn đã trình bày. Trình biên dịch có biến câu lệnh switch thành mã bảo nó bỏ qua X # của mã byte và JVM làm như vậy không?
Chris Okyen

Ngoài ra, tôi không hiểu cách thức bỏ qua này hoạt động ... Tôi biết một số M6800 asm, có giống như việc nhảy con trỏ đến ngăn xếp cuộc gọi X không ... Đừng để tất cả các câu lệnh của 2 trường hợp được gọi mặc định như vậy tại sao họ sẽ bị bỏ qua Làm thế nào nó biết để bỏ qua chúng. Và tại sao bạn chỉ bỏ qua các câu lệnh (hoặc hành động) được gọi do các trường hợp là đúng ... Không phải là mã chuyển đổi {và case: code và default: và} code cần được bỏ qua mã op hoặc đó không phải là thực "opcode" nhưng logic chỉ đưa vào các ngôn ngữ lập trình cấp cao hơn như C và Java và Pascal?
Chris Okyen

@ChrisOkyen Tôi đã cố gắng minh họa khái niệm cơ bản. Nhận thức thực tế trong JVM được mô tả ở đây: artima.com/underthehood/flowP.html
Scarfridge

0

Để trả lời câu hỏi đã chỉnh sửa (có dấu ngắt)

Họ sẽ đánh giá các câu lệnh giống nhau, nếu và chỉ khi các điều kiện để nhập từng khối là như nhau.

Để trả lời câu hỏi chủ quan, của

đưa ra một góc suy nghĩ về sự tương đồng được bảo tồn và cả những gì chúng (khác nhau / giống nhau) sâu bên dưới

So sánh hai điều khiến bạn mất tập trung vào những gì từng được thiết kế để nhanh chóng thể hiện.

Một switchcú pháp tập trung vào việc so sánh để bạn có thể theo dòng chảy dựa trên các trường hợp của nó.

Trong khi một ifmô tả một điều kiện duy nhất để nhập một khối.

Về cơ bản mã chỉ "đọc" khác nhau.

Ví dụ, bạn có một cái wordtrong đầu và bạn muốn tra cứu nó trong từ điển.

Một công tắc sẽ đọc như sau: giữ chữ cái bắt đầu trong đầu của bạn, rồi đưa ngón tay cái qua bảng chữ cái, sau đó từ bỏ nếu nó không bắt đầu bằng chữ cái đó.

Trong khi một loạt các khối if-if khác sẽ đọc như sau: từ có bắt đầu bằng chữ cái không? lặp đi lặp lại nhiều lần, rồi bỏ cuộc.

Nếu bạn đang cố gắng giải thích cách chuyển đổi hoạt động với một lập trình viên mới (người quen thuộc với các khối, thì có thể dễ dàng giải thích nó như sau:

if( boolean_expression_1 ) {
  statement_1;
  return;
}

if( boolean_expression_2 ) {
  statement_2;
  return;
}

default_statement;
return;

Bây giờ ví dụ trước phá vỡ những gì thường được dạy trong trường học, nhưng trở về sớm và trở lại thường đôi khi dễ đọc hơn và nhanh như trong vm dựa trên ngăn xếp.

Cần có sự tối ưu hóa cho các công tắc trên các nguyên thủy, vì vậy lựa chọn sử dụng khối điều khiển nào sẽ dựa trên những gì bạn đang so sánh.

Hãy nhớ rằng dài dòng switchvà các iftuyên bố có xu hướng trở nên rất dài dòng, khó duy trì và cũng làm giảm hiệu suất vì nhiều điều kiện sẽ phải được kiểm tra.

Bạn có thể muốn xem xét một Hashlớp / hàm ẩn danh hoặc một mẫu lệnh, thay vì các khối điều khiển dài với nhiều điều kiện.

Băm và mẫu lệnh cho phép mã thực hiện nhanh hơn và cải thiện khả năng duy trì của mã.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.