Bắt nhiều ngoại lệ cùng một lúc trong Scala


Câu trả lời:


165

Bạn có thể liên kết toàn bộ mẫu với một biến như thế này:

try {
   throw new java.io.IOException("no such file")
} catch {
   // prints out "java.io.IOException: no such file"
   case e @ (_ : RuntimeException | _ : java.io.IOException) => println(e)
}

Xem Đặc tả Ngôn ngữ Scala trang 118 đoạn 8.1.11 được gọi là Các lựa chọn thay thế Mẫu.

Xem Khớp mẫu hình đã được Unleashed để tìm hiểu sâu hơn về đối sánh mẫu hình trong Scala.


mà không vượt qua máng sự sbt clean coverage test coverageReporttại thời điểm viết bài ... github.com/scoverage/sbt-scoverage/issues/257
Yordan Georgiev

32

Khi bạn có quyền truy cập vào các khả năng đối sánh mẫu đầy đủ của scala trong mệnh đề bắt, bạn có thể làm được nhiều điều:

try {
  throw new IOException("no such file")
} catch {
  case _ : SQLException | _ : IOException => println("Resource failure")
  case e => println("Other failure");
}

Lưu ý rằng nếu bạn cần viết lại cùng một trình xử lý, bạn có thể tạo cấu trúc điều khiển của riêng mình cho điều đó:

def onFilesAndDb(code: => Unit) { 
  try { 
    code 
  } catch {
    your handling code 
  }
}

Một số phương pháp như vậy có sẵn trong đối tượng scala.util.control.Exceptions . fail, failAsValue, xử lý có thể chỉ là những gì bạn cần

Chỉnh sửa: Trái ngược với những gì được nói bên dưới, các mẫu thay thế có thể bị ràng buộc, vì vậy giải pháp được đề xuất không cần thiết phải phức tạp. Xem giải pháp @agilesteel

Thật không may, với giải pháp này, bạn không có quyền truy cập vào trường hợp ngoại lệ mà bạn sử dụng các mẫu thay thế. Theo hiểu biết của tôi, bạn không thể ràng buộc vào một mẫu thay thế với trường hợp e @ (_ : SqlException | _ : IOException). Vì vậy, nếu bạn cần quyền truy cập vào ngoại lệ, bạn phải lồng ghép các trình kết hợp:

try {
  throw new RuntimeException("be careful")
} catch  {
  case e : RuntimeException => e match {
    case _ : NullPointerException | _ : IllegalArgumentException => 
      println("Basic exception " + e)
    case a: IndexOutOfBoundsException => 
      println("Arrray access " + a)
    case _ => println("Less common exception " + e)
  }
  case _ => println("Not a runtime exception")
}

Thật thú vị, tôi chưa từng thấy các lựa chọn thay thế mẫu trước đây. Tôi nghĩ chúng không có trong PinS .
kassens

1
Ràng buộc một mẫu thay thế hoạt động và đặc biệt hữu ích trong trường hợp này. Biến bị ràng buộc thậm chí còn nhận được dưới dạng siêu kiểu phổ biến cụ thể nhất của các lựa chọn thay thế. Tổ chức những người tuần hành là không cần thiết. Tôi sẽ ủng hộ câu trả lời của bạn nếu bạn cập nhật câu trả lời như vậy.
Jean-Philippe Pellet

@ Jean-Philippe: Tuyệt vời !! Tôi đã thử trước khi trả lời và không thể làm cho nó hoạt động. Kiểm tra thông số kỹ thuật có lẽ quá nhanh, tôi nghĩ nó cũng nói như vậy (ở trang 113 thay thế là Mẫu và bạn chỉ có thể ràng buộc trên Mẫu 3). Cú pháp là gì?
Didier Dupont

16

Bạn cũng có thể sử dụng scala.util.control.Exception:

import scala.util.control.Exception._
import java.io.IOException

handling(classOf[RuntimeException], classOf[IOException]) by println apply { 
  throw new IOException("foo") 
}

Ví dụ cụ thể này có thể không phải là ví dụ tốt nhất để minh họa cách bạn có thể sử dụng nó, nhưng tôi thấy nó khá hữu ích trong nhiều trường hợp.


0

Đây là cách duy nhất cho tôi, vượt qua khó khăn sbt clean coverage test coverageReportmà không ném ra ngoại lệ phân tích cú pháp khó chịu ...

try {
   throw new CustomValidationException1( 
      CustomErrorCodeEnum.STUDIP_FAIL,
      "could be throw new CustomValidationException2")
    } catch {
    case e
      if (e.isInstanceOf[CustomValidationException1] || e
      .isInstanceOf[CustomValidationException2]) => {
        // run a common handling for the both custom exceptions
        println(e.getMessage)
        println(e.errorCode.toString) // an example of common behaviour 
    }
    case e: Exception => {
      println("Unknown error occurred while reading files!!!")
      println(e.getMessage)
      // obs not errorCode available ...
    }
}

    // ... 
    class CustomValidationException1(val errorCode: CustomErrorCodeEnum, val message: String)
    class CustomValidationException2(val errorCode: CustomErrorCodeEnum, val message: String)
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.