2010-03-24 4 views

답변

93

오버로드는 좀 더 열심히 함수에 방법을 들어 올릴 수 있습니다 : 당신은 선택적으로 오버로드 된 메서드의 세트 중 하나 가져올 수 없습니다

object A { 
    def foo(a: Int) = 0 
    def foo(b: Boolean) = 0 
    def foo(a: Int, b: Int) = 0 

    val function = foo _ // fails, must use = foo(_, _) or (a: Int) => foo(a) 
} 

.

모호함이 매개 변수 유형에 인수를 적응하는 암시 적 전망을 적용 할 때 발생하는 것으로 큰 기회가있다 :

scala> implicit def S2B(s: String) = !s.isEmpty        
S2B: (s: String)Boolean 

scala> implicit def S2I(s: String) = s.length        
S2I: (s: String)Int 

scala> object test { def foo(a: Int) = 0; def foo(b: Boolean) = 1; foo("") } 
<console>:15: error: ambiguous reference to overloaded definition, 
both method foo in object test of type (b: Boolean)Int 
and method foo in object test of type (a: Int)Int 
match argument types (java.lang.String) 
     object test { def foo(a: Int) = 0; def foo(b: Boolean) = 1; foo("") } 

그것은 조용히 사용할 기본 매개 변수를 렌더링 할 수는 :

object test { 
    def foo(a: Int) = 0; 
    def foo(a: Int, b: Int = 0) = 1 
} 

개별적으로, 이러한 이유들은 당신이 완전히 오버로드를 피하도록 강요하지 않습니다. 나는 더 큰 문제를 놓치고있는 것처럼 느껴진다.

UPDATE

증거는 최대 적재된다.

UPDATE 2

  • 당신은 (현재) 패키지 객체의 메소드를 오버로드 할 수 없습니다.
  • 해당 API 호출자의 경우 적용 가능한 오류는 harder to diagnose입니다.

UPDATE 3

  • 정적 과부하 해상도 강탈 할 수있는 모든 형태의 안전성의 API :

    스칼라> 오브젝트 O {DEF 적용 [T (TS : T의 *) =(); =()} 정의 오브젝트 O

    스칼라> O ((I : 문자열) => F (I)) // 죄송 I 통화 의미 제 : DEF ((문자열 => INT) f)에 적용 내가 ... 길 라드와 제이슨 (retronym가) 가능하면 과부하를 방지하기위한 모든 아주 좋은 이유는 줄

+2

현재 스칼라에는 특정 경우에 오버로딩으로 인해 발생하는 버그가 있습니다. https://issues.scala-lang.org/browse/SI-7596. – cvogt

+0

처음 두 가지 문제는 오버로드의 모든 유효한 사용에 영향을 미치지 않습니다. 3 번째 호에 대한 [버그 보고서] (https://issues.scala-lang.org/browse/SI-7856)를 제출했습니다. [기본값에 대한 제한은 선택입니다.] (http://stackoverflow.com/a/4652681/615784) 이론적으로는 수정 될 수 있습니다. '_.foo' 문제는 Scala의 제한된 타입 추론으로, 오버로드가 아닙니다. 여러분은 그 질문에 답해 주지만, 그 이유 중 일부는 개선 될 수있는 Scala의 다른 약점 때문입니다. 오버로딩은 논리적 결합을 다운 캐스팅하는 런타임보다 효율적이며 이름의 카디 전 곱은 시끄럽고 공유 된 의미와의 연결을 끊습니다. –

+0

형식 클래스는 경우에 따라 오버로드의 대안을 제공합니다. 자석 패턴 (http://spray.io/blog/2012-12-13-the-magnet-pattern/)은이 아이디어를 흥미로운 방식으로 푸시합니다. – retronym

2

내가 조언 특히 스칼라 의미하지 생각 않지만, 일반적으로 OO을 위해 (지금까지 내가 스칼라는 최상의 OO와 기능 사이에 있어야하는데 알고있다).

을 재정의하면 괜찮습니다. 다형성의 핵심이며 객체 지향 디자인의 핵심입니다.

반면에은 오버로드가 더 문제가됩니다. 메서드 오버로딩을 사용하면 실제로 어떤 메서드가 호출되는지를 구분하기가 어렵고 실제로 혼란의 원인이 될 수 있습니다. 또한 과부하가 실제로 필요한 이유는 거의 없습니다. 문제는 대부분 다른 방법으로 해결 될 수 있으며 과부하가 냄새라고 동의합니다.

여기에 "과부하가 혼란의 원천"이라는 뜻을 멋지게 설명하는 an article입니다. 이것이 낙심 한 주된 이유라고 생각합니다. 자바 용이지만 스칼라에도 적용된다고 생각합니다.

+1

그리고 Scala isn 어쨌든 OO 언어가 주로 사용됩니다. –

+0

@ewernli : 유용한 링크입니다.이 링크를 포함 시키려면 편집하십시오. – missingfaktor

+3

@ewenli - Jorge는 scala 커뮤니티에서 잘 알려져 있으며 Rahul이 제공 한 링크는 호르헤의 스칼라 팁 중 하나인데 아직 질문의 의도였던 스칼라에 대한 과부하가 왜 나쁜지에 대한 대답은 아무것도 없습니다. 왜 어떤 식 으로든 그 질문이 혼란 스럽다고 결정한 이유가 없습니다. - 당신은 단지 정답이 아니기 때문에 대답에서 제거해야합니다. -1 –

6

이유를 찾고되지 않았을 때 과부하하지만 누군가는 f의 반환 형식을 변경했습니다. Gilad의 이유는 오버로드가 일반적으로 문제가되는 이유에 초점을 맞추는 반면 Jason의 이유는 다른 Scala 기능과 관련하여 문제가있는 이유에 초점을두고 있습니다.

Jason의 목록에서 오버로딩이 형식 유추와 제대로 상호 작용하지 않는다고 추가합니다. 고려 :

val x = ... 
foo(x) 

x의 추론 유형의 변화를 호출되는있는 foo 방법을 변경할 수 있습니다. 값이x은 변경하지 않아도됩니다. 모든 이유에서 발생할 수있는 x의 유추 유형 만 변경하면됩니다.

주어진 이유로 (그리고 내가 잊어 버린 것이 틀림 없음), 메소드 오버로딩은 가능한 한 아껴서 사용해야한다고 생각합니다.

+2

그런 일이 일어나지 않게하려면 x에 대한 유형을 선언하십시오. 선언하지 않으면 변경을 원한다고 말하는 것입니다. 'foo'의 의미는 매개 변수 수가 같은 모든 과부하에 대해 동일해야합니다. 그렇지 않으면 잘못 설계되었습니다. 추측 변경의 기괴한 케스케이드 범위를 제한하는 것과 같이 공개 메소드는 항상 리턴 유형을 선언해야합니다. 이 문제는 버전 간 스칼라 바이너리 호환성에 영향을 미치는 문제 중 하나라고 생각합니다. –