Как я могу скрыть методы в F #? - PullRequest
5 голосов
/ 05 марта 2010

В настоящее время я реализую инфраструктуру Spec в F # и хочу скрыть методы Equals, GetHashCode и т. Д. Для моего типа should, чтобы API не загромождался этими.

Я знаю, что в C # это достигается тем, что класс реализует такой интерфейс:

using System;
using System.ComponentModel;

public interface IFluentInterface
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    bool Equals(object other);

    [EditorBrowsable(EditorBrowsableState.Never)]
    string ToString();

    [EditorBrowsable(EditorBrowsableState.Never)]
    int GetHashCode();

    [EditorBrowsable(EditorBrowsableState.Never)]
    Type GetType();
}

Я пытался сделать то же самое в F #:

type IFluentInterface = interface

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    abstract Equals : (obj) -> bool

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    abstract ToString: unit -> string

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    abstract GetHashCode: unit -> int

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    abstract GetType : unit -> Type 
end

Реализовано это в моем виде:

        interface IFluentInterface with
        member x.Equals(other) = x.Equals(other)
        member x.ToString()    = x.ToString() 
        member x.GetHashCode() = x.GetHashCode()
        member x.GetType()     = x.GetType() 

но безуспешно.

Я также пытался переопределить методы в моем типе и добавить атрибут таким образом, но это тоже не помогло.

Таким образом, остается вопрос, как я могу очистить мой API?

Edit:

Благодаря помощи (см. Ниже) мне удалось решить мою проблему.

В итоге, .Equals и .GetHashCode можно скрыть с помощью [<NoEquality>] [<NoComparison>], но это также изменит семантику.

Скрытие через атрибуты EditorBrowsable не работает.

Единственный способ иметь чистый API и при этом иметь возможность перегружать методы - это сделать эти члены метода статическими.

Полученный класс можно найти, просмотрев внутри моего проекта FSharpSpec .

Обсуждаемый тип можно найти здесь .

Спасибо всем, кто помог мне решить эту проблему.

Ура ...

Ответы [ 3 ]

5 голосов
/ 05 марта 2010

Повтор моего ответа от

http://cs.hubfs.net/forums/thread/13317.aspx

В F # вы можете запретить Equals & GetHashCode (и удалить их из intellisense), пометив тип с помощью атрибутов NoEquality и NoComparison, как показано ниже. Пользовательские методы также могут быть скрыты из списка intellisense с помощью атрибута устаревшего или атрибута CompilerMessage с IsHidden = true. Невозможно скрыть методы System.Object GetType и ToString от F # intellisense.

[<NoEquality; NoComparison>]
type Foo() =
    member x.Bar() = ()
    member x.Qux() = ()
    [<System.Obsolete>]
    member x.HideMe() = ()
    [<CompilerMessage("A warning message",99999,IsError=false,IsHidden=true)>]
    member x.WarnMe() = ()

let foo = new Foo()
foo.  // see intellisense here
4 голосов
/ 05 марта 2010

Кроме того, вы можете разработать библиотеку, используя альтернативный стиль, используя функции, заключенные в модуль. Это обычный способ написания функционального кода на F #, и тогда вам не нужно будет скрывать какие-либо стандартные методы .NET. Чтобы завершить пример, заданный 'kvb', вот пример объектно-ориентированного решения:

type MyNum(n:int) =
  member x.Add(m) = MyNum(n+m)
  member x.Mul(m) = MyNum(n*m)

let n = new MyNum(1)
n.Add(2).Mul(10) // 'ToString' shows in the IntelliSense

Функциональный способ написания кода может выглядеть следующим образом:

type Num = Num of int
module MyNum =
  let create n = Num n
  let add m (Num n) = Num (m + n)
  let mul m (Num n) = Num (m * n)

MyNum.create 1 |> MyNum.add 2 |> MyNum.mul 10

Если вы введете MyNum., F # IntelliSense покажет функции, определенные в модуле, поэтому вы не увидите никакого шума в этом случае.

3 голосов
/ 05 марта 2010

Я не думаю, что в F # вообще есть способ сделать это.В конкретном случае .Equals и .GetHashCode вы можете сделать их непригодными для использования, добавив атрибут [<NoEquality>] к вашему типу, но на самом деле это имеет смысловой эффект в дополнение к сокрытию этих методов.

РЕДАКТИРОВАТЬ

Стоит также упомянуть, что свободно используемые интерфейсы редко используются в F #, так как вместо этого гораздо проще использовать комбинаторы и конвейеризацию.Например, представьте, что мы хотим создать способ создания арифметических выражений.Вместо

let x = Expressions.MakeExpr(1).Add(2).Mul(3).Add(4)

Я думаю, что большинство пользователей F # предпочли бы писать

open Expressions
let x = 
  1
  |> makeExpr
  |> add 2
  |> mul 3
  |> add 4

С этим стилем нет необходимости скрывать элементы, потому что выражения передаются в комбинаторы, а не вызываютметоды построителя выражений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...