[SCALA] 스칼라의 오버로드 생성자와 함께 자신의 예외를 정의
SCALA스칼라의 오버로드 생성자와 함께 자신의 예외를 정의
자바에서 예외가 적어도 네 가지 생성자를 가지고 :
Exception()
Exception(String message)
Exception(String message, Throwable cause)
Exception(Throwable cause)
당신이 당신의 자신의 확장을 정의하려면, 당신은 단지 하위 예외를 선언하고 corresponden 슈퍼 생성자를 호출 원하는 각 생성자를 구현해야
당신은 어떻게 스칼라에서 같은 일을 달성 할 수 있습니까?
지금까지 지금은이 글이 SO의 대답을했다,하지만 난 그런 일반적인 일을 달성하는 쉬운 방법이있을 의심
해결법
-
==============================
1.원인의 기본값은 null입니다. 그리고 메시지는 하나에 cause.toString ()는 null입니다 :
원인의 기본값은 null입니다. 그리고 메시지는 하나에 cause.toString ()는 null입니다 :
val e1 = new RuntimeException() e.getCause // res1: java.lang.Throwable = null e.getMessage //res2: java.lang.String = null val cause = new RuntimeException("cause msg") val e2 = new RuntimeException(cause) e.getMessage() //res3: String = java.lang.RuntimeException: cause msg
그냥 기본값을 사용할 수 있도록 :
class MyException(message: String = null, cause: Throwable = null) extends RuntimeException(MyException.defaultMessage(message, cause), cause) object MyException { def defaultMessage(message: String, cause: Throwable) = if (message != null) message else if (cause != null) cause.toString() else null } // usage: new MyException(cause = myCause) // res0: MyException = MyException: java.lang.RuntimeException: myCause msg
-
==============================
2.물론, 이것은 내가 지금까지 발견했습니다 최고입니다
물론, 이것은 내가 지금까지 발견했습니다 최고입니다
class MissingConfigurationException private(ex: RuntimeException) extends RuntimeException(ex) { def this(message:String) = this(new RuntimeException(message)) def this(message:String, throwable: Throwable) = this(new RuntimeException(message, throwable)) } object MissingConfigurationException { def apply(message:String) = new MissingConfigurationException(message) def apply(message:String, throwable: Throwable) = new MissingConfigurationException(message, throwable) }
이 방법 당신은 "새로운 MissingConfigurationException"를 사용할 수 있습니다 또는는 동반자 개체에서 방법을 적용
어쨌든, 나는 아직 그것을 달성 할 수있는 간단한 방법이없는 것이 놀랍 네요
-
==============================
3.당신은 Throwable.initCause를 사용할 수 있습니다.
당신은 Throwable.initCause를 사용할 수 있습니다.
class MyException (message: String, cause: Throwable) extends RuntimeException(message) { if (cause != null) initCause(cause) def this(message: String) = this(message, null) }
-
==============================
4.나를 위해, 서로 동적 장력이 세 가지 요구가 나타납니다 :
나를 위해, 서로 동적 장력이 세 가지 요구가 나타납니다 :
하나는 3 번을 걱정하지 않는 경우,이 답변 (이 하나 피어는) 꽤 간결 보인다.
하나 개의 값 숫자 3이 가능한 번호 1에 가까운 2 으려고 시도하는 동안 그러나,이 솔루션은 아래 효과적으로 스칼라 API로 자바 널 누출을 캡슐화합니다.
class MyRuntimeException ( val optionMessage: Option[String], val optionCause: Option[Throwable], val isEnableSuppression: Boolean, val isWritableStackTrace: Boolean ) extends RuntimeException( optionMessage match { case Some(string) => string case None => null }, optionCause match { case Some(throwable) => throwable case None => null }, isEnableSuppression, isWritableStackTrace ) { def this() = this(None, None, false, false) def this(message: String) = this(Some(message), None, false, false) def this(cause: Throwable) = this(None, Some(cause), false, false) def this(message: String, cause: Throwable) = this(Some(message), Some(cause), false, false) }
당신이 MyRuntimeException 실제로 사용되는 경우 새로운를 사용하지 제거하고 싶은 경우에,이 동반자 개체를 추가 (이 단지 앞으로 모든 기존의 "마스터"클래스 생성자를 호출 적용의) :
object MyRuntimeException { def apply: MyRuntimeException = MyRuntimeException() def apply(message: String): MyRuntimeException = MyRuntimeException(optionMessage = Some(message)) def apply(cause: Throwable): MyRuntimeException = MyRuntimeException(optionCause = Some(cause)) def apply(message: String, cause: Throwable): MyRuntimeException = MyRuntimeException(optionMessage = Some(message), optionCause = Some(cause)) def apply( optionMessage: Option[String] = None, optionCause: Option[Throwable] = None, isEnableSuppression: Boolean = false, isWritableStackTrace: Boolean = false ): MyRuntimeException = new MyRuntimeException( optionMessage, optionCause, isEnableSuppression, isWritableStackTrace ) }
개인적으로, 나는 가능한 미래의 리팩토링을 용이하게하기 위해 가능한 한 너무 많은 코드로 새로운 운영자 실제로 억제를 사용하는 것을 선호합니다. 말했다 리팩토링은 공장 패턴에 강하게 발생하는 경우 특히 유용합니다. 내 최종 결과는, 더 자세한하면서, 클라이언트가 사용하기에 아주 좋은해야한다.
object MyRuntimeException { def apply: MyRuntimeException = MyRuntimeException() def apply(message: String): MyRuntimeException = MyRuntimeException(optionMessage = Some(message)) def apply(cause: Throwable): MyRuntimeException = MyRuntimeException(optionCause = Some(cause)) def apply(message: String, cause: Throwable): MyRuntimeException = MyRuntimeException(optionMessage = Some(message), optionCause = Some(cause)) def apply( optionMessage: Option[String] = None, optionCause: Option[Throwable] = None, isEnableSuppression: Boolean = false, isWritableStackTrace: Boolean = false ): MyRuntimeException = new MyRuntimeException( optionMessage, optionCause, isEnableSuppression, isWritableStackTrace ) } class MyRuntimeException private[MyRuntimeException] ( val optionMessage: Option[String], val optionCause: Option[Throwable], val isEnableSuppression: Boolean, val isWritableStackTrace: Boolean ) extends RuntimeException( optionMessage match { case Some(string) => string case None => null }, optionCause match { case Some(throwable) => throwable case None => null }, isEnableSuppression, isWritableStackTrace )
보다 정교한 RuntimeException의 패턴을 탐색 :
단지 원래의 질문에서 작은 도약 패키지 또는 API에 대한 전문들이 RuntimeException의 생태계를 만드는 욕망입니다. 아이디어는 특정 하위 예외의 새로운 생태계가 생성 할 수있는 "루트"의 RuntimeException을 정의하는 것입니다. 나를 위해, 캐치를 사용하고 오류의 특정 유형에 대한 악용 훨씬 쉽게 일치시키는 것이 중요했다.
예를 들어, I는 케이스 클래스를 생성 할 수 있도록 이전 상태들의 세트를 정의 유효성 확인 방법을 가지고있다. 실패 각 조건은 RuntimeException의 인스턴스를 생성합니다. 그리고 RuntimeInstances의 목록이 방법으로 반환됩니다. 이것은 클라이언트에게 그들이 응답을 처리하려는 방법을 결정하는 기능을 제공합니다; 목록 잡고 예외를 던져 뭔가 특정의 목록을 스캔하거나 매우 비싼 JVM 던져 명령을 참여하지 않고 호출 체인까지 전체 일을 밀어 것을 던져.
이 특정 문제 공간의 RuntimeException의 세 가지 다른 후손, 하나의 추상 (FailedPrecondition)와 두 개의 콘크리트 (FailedPreconditionMustBeNonEmptyList 및 FailedPreconditionsException)가 있습니다.
첫 번째, FailedPrecondition는 RuntimeException을, MyRuntimeException 매우 유사에 직계 후손이며, (직접 인스턴스 생성을 방지하기 위해) 추상적이다. FailedPrecondition는 인스턴스 팩토리 (new 연산자를 억제)와 같은 역할을하는 "컴패니언 오브젝트 특성"FailedPreconditionObject있다.
trait FailedPreconditionObject[F <: FailedPrecondition] { def apply: F = apply() def apply(message: String): F = apply(optionMessage = Some(message)) def apply(cause: Throwable): F = apply(optionCause = Some(cause)) def apply(message: String, cause: Throwable): F = apply(optionMessage = Some(message), optionCause = Some(cause)) def apply( optionMessage: Option[String] = None , optionCause: Option[Throwable] = None , isEnableSuppression: Boolean = false , isWritableStackTrace: Boolean = false ): F } abstract class FailedPrecondition ( val optionMessage: Option[String], val optionCause: Option[Throwable], val isEnableSuppression: Boolean, val isWritableStackTrace: Boolean ) extends RuntimeException( optionMessage match { case Some(string) => string case None => null }, optionCause match { case Some(throwable) => throwable case None => null }, isEnableSuppression, isWritableStackTrace )
둘째, FailedPreconditionMustBeNonEmptyList 간접 RuntimeException의 자손과 FailedPrecondition 직접적인 구체적인 구현이다. 그것은 동반자 객체와 클래스를 모두 정의합니다. 컴패니언 객체는 특성 FailedPreconditionObject 확장합니다. 그리고 클래스는 단순히 최종 더 이상의 확장을 방지하기 위해 추상 클래스 FailedPrecondition 마크를 확장합니다.
object FailedPreconditionMustBeNonEmptyList extends FailedPreconditionObject[FailedPreconditionMustBeNonEmptyList] { def apply( optionMessage: Option[String] = None , optionCause: Option[Throwable] = None , isEnableSuppression: Boolean = false , isWritableStackTrace: Boolean = false ): FailedPreconditionMustBeNonEmptyList = new FailedPreconditionMustBeNonEmptyList( optionMessage , optionCause , isEnableSuppression , isWritableStackTrace ) } final class FailedPreconditionMustBeNonEmptyList private[FailedPreconditionMustBeNonEmptyList] ( optionMessage: Option[String] , optionCause: Option[Throwable] , isEnableSuppression: Boolean , isWritableStackTrace: Boolean ) extends FailedPrecondition( optionMessage , optionCause , isEnableSuppression , isWritableStackTrace )
셋째, FailedPrecondition 예외는 실패 전제 조건 목록을 래핑하고 동적 예외 메시지의 발광 관리 RuntimeException의 직접 하위이다.
object FailedPreconditionsException { def apply(failedPrecondition: FailedPrecondition): FailedPreconditionsException = FailedPreconditionsException(List(failedPrecondition)) def apply(failedPreconditions: List[FailedPrecondition]): FailedPreconditionsException = tryApply(failedPreconditions).get def tryApply(failedPrecondition: FailedPrecondition): Try[FailedPreconditionsException] = tryApply(List(failedPrecondition)) def tryApply(failedPreconditions: List[FailedPrecondition]): Try[FailedPreconditionsException] = if (failedPreconditions.nonEmpty) Success(new FailedPreconditionsException(failedPreconditions)) else Failure(FailedPreconditionMustBeNonEmptyList()) private def composeMessage(failedPreconditions: List[FailedPrecondition]): String = if (failedPreconditions.size > 1) s"failed preconditions [${failedPreconditions.size}] have occurred - ${failedPreconditions.map(_.optionMessage.getOrElse("")).mkString("|")}" else s"failed precondition has occurred - ${failedPreconditions.head.optionMessage.getOrElse("")}" } final class FailedPreconditionsException private[FailedPreconditionsException] ( val failedPreconditions: List[FailedPrecondition] ) extends RuntimeException(FailedPreconditionsException.composeMessage(failedPreconditions))
그리고 전체적으로 깔끔한 것들로 그 함께 모두를 데리고, 나는 개체 FailedPreconditionsException 내에서 모두 FailedPrecondition 및 FailedPreconditionMustBeNonEmptyList 놓습니다. 그리고 이것은 최종 결과의 모습이 좋아하는 것입니다 :
object FailedPreconditionsException { trait FailedPreconditionObject[F <: FailedPrecondition] { def apply: F = apply() def apply(message: String): F = apply(optionMessage = Some(message)) def apply(cause: Throwable): F = apply(optionCause = Some(cause)) def apply(message: String, cause: Throwable): F = apply(optionMessage = Some(message), optionCause = Some(cause)) def apply( optionMessage: Option[String] = None , optionCause: Option[Throwable] = None , isEnableSuppression: Boolean = false , isWritableStackTrace: Boolean = false ): F } abstract class FailedPrecondition ( val optionMessage: Option[String] , val optionCause: Option[Throwable] , val isEnableSuppression: Boolean , val isWritableStackTrace: Boolean ) extends RuntimeException( optionMessage match { case Some(string) => string case None => null }, optionCause match { case Some(throwable) => throwable case None => null }, isEnableSuppression, isWritableStackTrace ) object FailedPreconditionMustBeNonEmptyList extends FailedPreconditionObject[FailedPreconditionMustBeNonEmptyList] { def apply( optionMessage: Option[String] = None , optionCause: Option[Throwable] = None , isEnableSuppression: Boolean = false , isWritableStackTrace: Boolean = false ): FailedPreconditionMustBeNonEmptyList = new FailedPreconditionMustBeNonEmptyList( optionMessage , optionCause , isEnableSuppression , isWritableStackTrace ) } final class FailedPreconditionMustBeNonEmptyList private[FailedPreconditionMustBeNonEmptyList] ( optionMessage: Option[String] , optionCause: Option[Throwable] , isEnableSuppression: Boolean , isWritableStackTrace: Boolean ) extends FailedPrecondition( optionMessage , optionCause , isEnableSuppression , isWritableStackTrace ) def apply(failedPrecondition: FailedPrecondition): FailedPreconditionsException = FailedPreconditionsException(List(failedPrecondition)) def apply(failedPreconditions: List[FailedPrecondition]): FailedPreconditionsException = tryApply(failedPreconditions).get def tryApply(failedPrecondition: FailedPrecondition): Try[FailedPreconditionsException] = tryApply(List(failedPrecondition)) def tryApply(failedPreconditions: List[FailedPrecondition]): Try[FailedPreconditionsException] = if (failedPreconditions.nonEmpty) Success(new FailedPreconditionsException(failedPreconditions)) else Failure(FailedPreconditionMustBeNonEmptyList()) private def composeMessage(failedPreconditions: List[FailedPrecondition]): String = if (failedPreconditions.size > 1) s"failed preconditions [${failedPreconditions.size}] have occurred - ${failedPreconditions.map(_.optionMessage.getOrElse("")).mkString("|")}" else s"failed precondition has occurred - ${failedPreconditions.head.optionMessage.getOrElse("")}" } final class FailedPreconditionsException private[FailedPreconditionsException] ( val failedPreconditions: List[FailedPreconditionsException.FailedPrecondition] ) extends RuntimeException(FailedPreconditionsException.composeMessage(failedPreconditions))
그리고 이것은 클라이언트가 자신의 예외 유도라는 FailedPreconditionMustBeNonEmptyString을 만들 수 위의 코드를 사용하기 같을 것이다 것입니다 :
object FailedPreconditionMustBeNonEmptyString extends FailedPreconditionObject[FailedPreconditionMustBeNonEmptyString] { def apply( optionMessage: Option[String] = None , optionCause: Option[Throwable] = None , isEnableSuppression: Boolean = false , isWritableStackTrace: Boolean = false ): FailedPreconditionMustBeNonEmptyString = new FailedPreconditionMustBeNonEmptyString( optionMessage , optionCause , isEnableSuppression , isWritableStackTrace ) } final class FailedPreconditionMustBeNonEmptyString private[FailedPreconditionMustBeNonEmptyString] ( optionMessage: Option[String] , optionCause: Option[Throwable] , isEnableSuppression: Boolean , isWritableStackTrace: Boolean ) extends FailedPrecondition( optionMessage , optionCause , isEnableSuppression , isWritableStackTrace )
그리고이 예외의 사용은 다음과 같습니다 :
throw FailedPreconditionMustBeNonEmptyString()
나는 그렇게 어려운 특정에서의 RuntimeException을-ifying 스칼라 또는 내가 자바 때 너무 편안 성장있는 더 일반적인 "예외 생태계 '로 확장하는 구체적이고 포괄적 인 모두있는 아무것도 가까이 위치를 찾을 때문에 원래의 질문에 대답 잘 넘어 갔다 .
내가 의견을 듣고 싶네요 내 솔루션 세트에 (에 변화가 아닌 "와우 너무 자세한 나를 위해의 방법입니다. 그"). 그리고 추가 최적화 또는 나는이 패턴의 클라이언트에 대해 생성 한 값이나 간결성의 손실없이 상세를 줄일 수있는 방법을 사랑합니다.
-
==============================
5.시도 / catch 블록에서 스칼라 패턴 매칭은 인터페이스에서 작동합니다. 내 솔루션은 예외 이름에 대한 인터페이스를 사용하여 별도의 클래스 인스턴스를 사용하는 것입니다.
시도 / catch 블록에서 스칼라 패턴 매칭은 인터페이스에서 작동합니다. 내 솔루션은 예외 이름에 대한 인터페이스를 사용하여 별도의 클래스 인스턴스를 사용하는 것입니다.
trait MyException extends RuntimeException class MyExceptionEmpty() extends RuntimeException with MyException class MyExceptionStr(msg: String) extends RuntimeException(msg) with MyException class MyExceptionEx(t: Throwable) extends RuntimeException(t) with MyException object MyException { def apply(): MyException = new MyExceptionEmpty() def apply(msg: String): MyException = new MyExceptionStr(msg) def apply(t: Throwable): MyException = new MyExceptionEx(t) } class MyClass { try { throw MyException("oops") } catch { case e: MyException => println(e.getMessage) case _: Throwable => println("nope") } }
인스턴스화 MyClass에 출력합니다 "죄송합니다".
-
==============================
6.여기 로마 - 보리 소프하지만 더 형태 보증 @의 것과 유사한 방식이다.
여기 로마 - 보리 소프하지만 더 형태 보증 @의 것과 유사한 방식이다.
case class ShortException(message: String = "", cause: Option[Throwable] = None) extends Exception(message) { cause.foreach(initCause) }
그런 다음 자바 방식으로 예외를 만들 수 있습니다 :
throw ShortException() throw ShortException(message) throw ShortException(message, Some(cause)) throw ShortException(cause = Some(cause))
from https://stackoverflow.com/questions/10925268/define-your-own-exceptions-with-overloaded-constructors-in-scala by cc-by-sa and MIT license
'SCALA' 카테고리의 다른 글
[SCALA] -127와 다시 문자열을 바이트 배열에 .. 문제 (0) | 2019.11.28 |
---|---|
[SCALA] 추상 클래스를 구현 대 특색을 가진 스칼라 클라이언트 구성 (0) | 2019.11.28 |
[SCALA] 왜 튜플에 대한 스칼라의 구문은 매우 특별하다? (0) | 2019.11.28 |
[SCALA] 멀티 클래스 분류 예 불꽃 (0) | 2019.11.28 |
[SCALA] 어떻게 JSON으로 DataFrame를 변환하는? (0) | 2019.11.28 |