스칼라에서 내장 유형에 메소드를 추가 할 수 있습니까?
-
08-07-2019 - |
문제
내장 유형 (예 : Double)에 메소드를 추가하여 infix
운영자. 그게 가능합니까?
해결책
예 그리고 아니오. 예, 당신은 그것을 만들 수 있습니다 ~인 것 같다 당신이 방법을 추가 한 것처럼 double
. 예를 들어:
class MyRichDouble(d: Double) {
def <>(other: Double) = d != other
}
implicit def doubleToSyntax(d: Double) = new MyRichDouble(d)
이 코드는 이전에 불가능한 것을 추가합니다 <>
유형의 모든 객체에 대한 연산자 Double
. 그 속도 doubleToSyntax
방법은 자격없이 호출 될 수 있도록 범위에 있으면 다음이 작동합니다.
3.1415 <> 2.68 // => true
대답의 "아니오"부분은 당신이 실제로 아무것도 추가하지 않는다는 사실에서 비롯됩니다. Double
수업. 대신, 당신은 전환을 만들고 있습니다 Double
원하는 방법을 정의하는 새로운 유형으로. 이것은 많은 역동적 인 언어가 제공하는 오픈 클래스보다 훨씬 강력한 기술 일 수 있습니다. 또한 완전히 유형-안전합니다. :-)
당신이 알아야 할 몇 가지 제한 사항 :
- 이 기술은 당신을 허용하지 않습니다 제거하다 또는 재정의 기존 방법은 새로운 방법을 추가하십시오
- 암시 적 변환 방법 (이 경우,
doubleToSyntax
) 원하는 확장 방법을 사용할 수 있으려면 절대적으로 현장이어야합니다.
관용적으로, 암시 적 변환은 싱글 톤 객체 내에 배치되고 가져옵니다 (예 : import Predef._
)) 또는 특성 내에서 상속 (예 : class MyStuff extends PredefTrait
).
약간의 따로 : Scala의 "Infix 연산자"는 실제로 방법입니다. 와 관련된 마법은 없습니다 <>
디픽스가 될 수있는 메소드, 파서는 단순히 그런 식으로 받아들입니다. 원하는 경우 "일반 메소드"를 Infix 연산자로 사용할 수도 있습니다. 예를 들어, Stream
클래스는 a를 정의합니다 take
단일을 취하는 방법 Int
매개 변수 및 새를 반환합니다 Stream
. 이것은 다음과 같은 방식으로 사용할 수 있습니다.
val str: Stream[Int] = ...
val subStream = str take 5
그만큼 str take 5
표현은 말 그대로 동일합니다 str.take(5)
.
다른 팁
이 기능은 클래스 수행 오류 추정을 구현하는 데 유용합니다.
object errorEstimation {
class Estimate(val x: Double, val e: Double) {
def + (that: Estimate) =
new Estimate(this.x + that.x, this.e + that.e)
def - (that: Estimate) =
new Estimate(this.x - that.x, this.e + that.e)
def * (that: Estimate) =
new Estimate(this.x * that.x,
this.x.abs*that.e+that.x.abs*this.e+this.e*that.e)
def / (that: Estimate) =
new Estimate(this.x/that.x,
(this.x.abs*that.e+that.x.abs*this.e)/(that.x.abs*(that.x.abs-that.e)))
def +- (e2: Double) =
new Estimate(x,e+e2)
override def toString =
x + " +- " + e
}
implicit def double2estimate(x: Double): Estimate = new Estimate(x,0)
implicit def int2estimate(x: Int): Estimate = new Estimate(x,0)
def main(args: Array[String]) = {
println(((x: Estimate) => x+2*x+3*x*x)(1 +- 0.1))
// 6.0 +- 0.93
println(((x: Estimate) => (((y: Estimate) => y*y + 2)(x+x)))(1 +- 0.1))
// 6.0 +- 0.84
def poly(x: Estimate) = x+2*x+3/(x*x)
println(poly(3.0 +- 0.1))
// 9.33333 +- 0.3242352
println(poly(30271.3 +- 0.0001))
// 90813.9 +- 0.0003
println(((x: Estimate) => poly(x*x))(3 +- 1.0))
// 27.037 +- 20.931
}
}