2011-03-10 1 views
2

인터페이스를 구현하는 여러 유형이 있습니다. 이러한 유형의 평등은 인터페이스 구성원에 따라 다릅니다. 각 유형에 대해 Equals 또는 op_Equality을 무시하지 않고 이러한 유형에 대해 동등 함을 한 번 정의 할 수 있습니까?유형 정의 외부에서 동등성 구현

편집 나는 어떤 이유로, 심지어 유형 IEntity을 구현하지 않는, =의 모든 사용을 오버라이드 다음을 시도했지만.

[<AutoOpen>] module Equality = let inline op_Equality (left:IEntity) (right:IEntity) = true 

는 또한 유연한 타입 (#IEntity)를 사용하여 시도. 같은 결과.

+0

내가 interfaces.It이는 추상 기본 클래스를 쉽게 할 수있을 것입니다 수행하는 방법에 표시되지 않습니다,하지만 난 당신이 이미 알고있는 것 같아요? – wmeyer

+0

예.정적 멤버 제약 조건을 실험했지만 인터페이스를 구현하는 유형에'op_Equality'를 제한하는 방법을 찾지 못했습니다. – Daniel

+0

편집 관련 : 멤버 함수 만 오버로드 될 수 있습니다. – wmeyer

답변

2

이다; 불행히도 F #에는 이에 상응하는 기능이 없습니다. 최상의 선택은 아마도 다음 옵션 중 하나 일 것입니다 :

  1. 인터페이스 대신 추상 기본 클래스를 사용하십시오.
  2. 유형 이외의 평등 방법을 작성한 다음 모든 구현을 연기하십시오. 예를 들어,

    let entityEquals (i1:IEntity) (i2:IEntity) = 
        i1.Member1 = i2.Member1 && 
        i1.Member2 = i2.Member2 && 
        ... 
    
    type MyEntity() = 
        interface IEntity with 
        member x.Member1 = ... 
        ... 
        override x.Equals(y) = 
         match y with 
         | :? IEntity as y -> entityEquals x y 
         | _ -> false 
        override x.GetHashCode() = 
         ... 
    

    보일러의 비트뿐만 아니라, 여기에 단점은 다른 사람이 당신의 IEntity 인터페이스를 구현하는 경우, 그들은 당신의 평등 방법을 사용하도록 강요되지 않습니다 - 그것은 옵트 인입니다.

  3. 당신이 IEntity의 평등 테스트에 사용 다른 연산자를 만듭니다

    let (==) (i1:IEntity) (i2:IEntity) = 
        i1.Member1 = i2.Member1 && 
        ... 
    

    이의 (큰) 단점은 그러한 등 튜플, 기록, 같은 IEntity를 보관 유형 (의 구조 평등 .)는이 연산자를 사용하여 해당 구성 요소를 비교하지 않으며 이로 인해 놀라운 코드가 손상 될 수 있습니다.

+0

추상 수업은 현재 매우 뜨겁습니다. – Daniel

+0

'mixin'과'trait'은 예약어입니다. 어떤 계획? 스칼라 (또는 아마도 개선 된 F # 변형)에서와 마찬가지로 형질이 매우 유용 할 것입니다. – Daniel

+0

아직 계획이 없습니다. – Brian

1

정적 인 방법으로이를 수행 할 방법이 없다고 생각합니다. 문제는 그 확장 회원 (예를 들어, 당신이 확장으로 op_Equality을 추가 한 경우) 정적 멤버 제약 (당신은 또한 op_Equality 요구 사항 inlin를 사용하여 =을 재정의 예를 들어, 경우)에 의해 무시됩니다.

F # 컴파일러에는 소스 코드 인 let inline GenericOne을 검색하는 데 도움이되는 FSharp.Core.dll을 컴파일 할 때만 사용할 수있는 특수 기능이 있습니다. 그것은 정적 유형 스위치와 같은 것을 사용합니다 - 그러나 이것은 단순한 필사자가 접근 할 수 없습니다.

동적 유형 테스트를 사용하는 것보다 더 좋은 아이디어는 없지만 인터페이스를 비교할 수있는 맞춤 연산자를 정의하는 것이 좋습니다.

참조를 들어

, 추악한 동적 접근 방식은 다음과 같습니다 당신이 할하려는 것은 유지 mixin 또는 typeclasses 다른 언어로 수 있습니다 뭔가

let inline (=) a b = 
    match a, b with 
    | :? IFoo as a, :? IFoo as b -> yourEquals a b 
    | _ -> a = b 
+0

필자는'inline'을 사용하여 * 평등을 구현하려고했지만, 반드시 * 평등을 사용하는 것은 아니지만 좋은 점이 있습니다. 내 목표는 인터페이스를 구현하는 모든 유형에 대해 한 번 동등성을 정의하여 전통적인 동등 의미를 얻는 것입니다. – Daniel