당신은 아마뿐만 아니라이 아이디어의 생각,하지만 이런 일에 대해 :
class StringOrIntOrDouble private(val first: Option[String], val second: Option[Int], val third: Option[Double]) {
def this(first: String) = this(Some(first), None, None)
def this(second: Int) = this(None, Some(second), None)
def this(third: Double) = this(None, None, Some(third))
def this(first: String, second: Int) = this(Some(first), Some(second), None)
def this(second: Int, third: Double) = this(None, Some(second), Some(third))
def this(first: String, third: Double) = this(Some(first), None, Some(third))
def this(first: String, second: Int, third: Double) = this(Some(first), Some(second), Some(third))
}
주요 생성자는 그래서 당신은 빈 인스턴스를 만들 수 없습니다 private
입니다. 물론 Product
및 equals
, hashCode
, toString
및 기타 유용한 것들을 케이스 클래스처럼 확장 할 수 있습니다 (단, 불변 값을 쉽게 깨뜨릴 수도 있음을 유의하십시오.) copy
.
불행히도, 일반 버전을 원한다면 (또는 두 유형에서 동일한 유형을 사용하는 경우) 이름이 지정된 메소드에 대한 모든 "부분 집합"생성자를 컴패니언 오브젝트로 이동해야합니다. 그렇지 않으면 유형 삭제로 인해 컴파일되지 않습니다 .
class TripleIor[+A, +B, +C] private(val first: Option[A], val second: Option[B], val third: Option[C]) {
}
object TripleIor {
def first[A](first: A) = new TripleIor[A, Nothing, Nothing](Some(first), None, None)
def second[B](second: B) = new TripleIor[Nothing, B, Nothing](None, Some(second), None)
def third[C](third: C) = new TripleIor[Nothing, Nothing, C](None, None, Some(third))
def firstAndSecond[A, B](first: A, second: B) = new TripleIor[A, B, Nothing](Some(first), Some(second), None)
def secondAndThird[B, C](second: B, third: C) = new TripleIor[Nothing, B, C](None, Some(second), Some(third))
def firstAndThird[A, C](first: A, third: C) = new TripleIor[A, Nothing, C](Some(first), None, Some(third))
def apply[A, B, C](first: A, second: B, third: C) = new TripleIor[A, B, C](Some(first), Some(second), Some(third))
}
더 급진적 인 방법은 sealed trait
7 서브 클래스와 같은 아이디어를 구현하는 것입니다하지만 난 그들이 사용하는 것이 훨씬 쉬울 것이라고 생각하지 않습니다. 또한 copy
을 유형에 안전한 방식으로 구현할 수 있지만 많은 타이핑 비용이 필요합니다 (여기에 표시되지 않음).
sealed trait TripleIor[A, B, C] extends Product {
def firstOption: Option[A]
def secondOption: Option[B]
def thirdOption: Option[C]
}
object TripleIor {
final case class First[A](first: A) extends TripleIor[A, Nothing, Nothing] {
override def firstOption: Option[A] = Some(first)
override def secondOption: Option[Nothing] = None
override def thirdOption: Option[Nothing] = None
}
final case class Second[B](second: B) extends TripleIor[Nothing, B, Nothing] {
override def firstOption: Option[Nothing] = None
override def secondOption: Option[B] = Some(second)
override def thirdOption: Option[Nothing] = None
}
final case class Third[C](third: C) extends TripleIor[Nothing, Nothing, C] {
override def firstOption: Option[Nothing] = None
override def secondOption: Option[Nothing] = None
override def thirdOption: Option[C] = Some(third)
}
final case class FirstSecond[A, B](first: A, second: B) extends TripleIor[A, B, Nothing] {
override def firstOption: Option[A] = Some(first)
override def secondOption: Option[B] = Some(second)
override def thirdOption: Option[Nothing] = None
}
final case class SecondThird[B, C](second: B, third: C) extends TripleIor[Nothing, B, C] {
override def firstOption: Option[Nothing] = None
override def secondOption: Option[B] = Some(second)
override def thirdOption: Option[C] = Some(third)
}
final case class FirstThird[A, C](first: A, third: C) extends TripleIor[A, Nothing, C] {
override def firstOption: Option[A] = Some(first)
override def secondOption: Option[Nothing] = None
override def thirdOption: Option[C] = Some(third)
}
final case class All[A, B, C](first: A, second: B, third: C) extends TripleIor[A, B, C] {
override def firstOption: Option[A] = Some(first)
override def secondOption: Option[B] = Some(second)
override def thirdOption: Option[C] = Some(third)
}
}
P. 여기에있는 모든 예제는 많은 유용하거나 필수적인 것을 구현하지 않는 아이디어를 설명하기위한 스케치 일뿐입니다.
3 개의 옵션 값으로 클래스를 사용하는 것이 좋습니다. 생성자를 private로 선언하고 정의 할 수 있다고 생각합니다. 조건을 검증하는 인스턴스를 생성하는 메소드는'Option [YourClass]','[Error, YourClass]'또는 코드베이스에서 사용중인 것을 반환 할 수 있습니다. – AlexITC
당신이 옳다고 생각합니다. 나는 타입을 사용하여 이것을 인코딩하는 더 자연스러운 방법이 있는지 궁금하다. – yhm
'cats.Ior' 또는 7 클래스'trait'을 사용하는 것이 이론적으로 건전한 접근 방법이라고 생각합니다. 'cats.Ior'의 소멸자는 3 방향'fold '이며, 그 결과 3 방향 유형에 대해 7 방향'fold'가됩니다. 이것은 어색함을 느낀다. 이 가치들을 가지고 무엇을 할 계획입니까? 세 가지 필드 사이에 어떤 자연스러운 우선 순위가 있습니까? 이 질문에 답하면 "올바른"인코딩을 결정하기가 더 쉽습니다. – ziggystar