LINUX.ORG.RU

Боюсь что способа добавить интерфейс без обёртки не получится. Дело в том, что для добавления\перегрузки метода используется Расширение типов.

Но там чётко говорится, что:

Методы расширения могут быть виртуальными или абстрактными. Они могут перегружать другие методы с этим же именем, но в случае неоднозначного вызова компилятор отдает предпочтение методам, не являющимся методами расширения.

А реализация GetHashCode есть у каждого класса, так что расширяющим методом её не перегрузить.

И да, абзацем выше указывается почему ими не получится сделать реализацию интерфейса - они компилируются в статические методы с неявной передачей первым аргументом экземпляра класса.

А вот с помощью наследования можно попробовать сделать то, что тебе нужно. К примеру так:

namespace TestLOR
{
  public class MyObj
  {
    public int Val { get; set; }

    public MyObj(int v) { Val = v; }
  }
}
#light

open System
open System.Collections.Generic
open TestLOR

type MyFObj (x) =
  inherit MyObj(x)
  override this.GetHashCode() = this.Val * this.Val


let lst = [MyFObj 2; MyFObj 3] 

[<EntryPoint>]
let main _ =
  printfn "%A" <| List.map (fun e -> e.GetHashCode()) lst
  Console.ReadLine()
  0
Norgat ★★★★★
()
Ответ на: комментарий от Norgat
type PrimitiveVertex = Element

type Vertex () = 
    inherit PrimitiveVertex()
    
    override this.Equals(v : obj) =
        match v with
        | :? Vertex as v -> (v.Id.OriginalId = this.Id.OriginalId)
        | _ -> false        
    
    override this.GetHashCode() = hash (this.Id.OriginalId)

а если Element имеет только конструктор () и мне нужно привести PrimitiveVertex к Vertex?

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от Norgat

Блин и интересно, а почему Set/Map не могут брать те GetHashCode для сравнения, какие есть. Да и если можно было бы дать Set/Map функцию для сравнения это было бы ну ооочень удобно

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

Поясни, что ты под этим имеешь в виду?

Norgat ★★★★★
()
Ответ на: комментарий от pseudo-cat

Попробуй сделать так:

type PVert (x) =
  let mutable _x = x  
  member x.X with get () = _x

type Vert (x, y) =
  inherit PVert(x)

  let mutable _y = y
  member x.Y with get () = _y
  new (e: PVert) = Vert(e.X, 0)

Т.е. добавить к PVert конструктор принимающий в качестве параметра объект базового класса. Ну а дальше делать честное приведение типов через создание нового объекта.

Norgat ★★★★★
()
Ответ на: комментарий от pseudo-cat

И да, причём тут GetHashCode то? Там же используется CompareTo метод из интерфейса IComparable для сравнения объектов. Типо такого:

type MyO (x) =
  let id = x
  member this.ID with get() = id

  interface IComparable with
    member x1.CompareTo(x2: obj) =
      if x1.ID = (x2 :?> MyO).ID 
        then 1
        else 0  

let lst1 = [MyO 1; MyO 1; MyO 1] |> Set.ofList

В результате в lst1 останется все 3 объекта.

Norgat ★★★★★
()
Ответ на: комментарий от Norgat

ну а почему бы тогда просто не написать

type PVert (x) =
  let _x = x  
  member x.X with get () = _x

  override this.Equals(v : obj) =
    match v with
    | :? Vertex as v -> 
        if (v.Id.OriginalId = this.Id.OriginalId)
            then 1 else 0
    | _ -> 0

проблема в том, что я постоянно получаю из C# объекты типа Element, а они не реализуют IComparable, а обёртывать их так как в коде выше не хотелось бы - их очень много и я боюсь за производительность. Пока что я вижу один выход - использовать вместо Map Dictionary

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

>> ну а почему бы тогда просто не написать

Я тебя там просто немного не так понял. Да так и нужно сделать.

Пока что я вижу один выход - использовать вместо Map Dictionary

Без обёртки не получится увы. Вопрос Dictionary устраивает? Если да, то юзай его, если нет, то можно сделать свою реализацию Map (вечерком гляну, код Map можно тут глянуть, если что: http://fsharppowerpack.codeplex.com/SourceControl/changeset/view/54799#970084)

Norgat ★★★★★
()
Ответ на: комментарий от pseudo-cat

Глянул я внимательно на код Map. Имхо, используй Dictionary, а с F# Map лучше не заморачивайся, она статическая, по аналогии с list (можешь попасть по производительности и без учёта обёрток). Ну а для Dictionary можно свой компаратор написать, так что это будет оптимальным выбором, имхо.

Norgat ★★★★★
()
Ответ на: комментарий от pseudo-cat

UPD

Я нашёл в PowerPack реализации Map и Set принимающие в качестве параметра компараторы.

Вот пример создания HashMultiMap, который использует пользовательский компаратор:

#light

open System
open System.Collections.Generic
open Microsoft.FSharp.Collections

type T () =
  interface IEqualityComparer<int> with
    member x.Equals (y, z) = true
    member x.GetHashCode (y) = 1 


type MyObj () =
  member x.Ti with get() = "sdb"

let mm = new HashMultiMap<int, MyObj> ( [1, MyObj()], new T() )

[<EntryPoint>]
let main _ =
  Console.ReadLine()
  0

п.с. требуется подключение сборки FSharp.PowerPack

сам PowerPack можно взять тут: http://fsharppowerpack.codeplex.com

интерфейс HashMultiMap: http://fsharppowerpack.codeplex.com/SourceControl/changeset/view/54799#685025

Norgat ★★★★★
()
Ответ на: UPD от Norgat

Да, кстати, я на неё и надеялся если честно, спасибо)

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

У меня сейчас нету под рукой F#. Точно не помню. Набери там #help;; - он выдаст список в котором будет команда загрузки сборки.

Norgat ★★★★★
()
Ответ на: комментарий от Norgat

P.S.

Я временно не смогу проверять F# код, т.к. по сносил дома системы и сейчас с чистого листа Debian себе настраиваю, надеюсь что F# без особых проблем заведётся под mono :)

Norgat ★★★★★
()
Ответ на: P.S. от Norgat

ок, у меня связка емакс + моно + фшарп вполне работает)

pseudo-cat ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.