Я в настоящее время реализую платформу Спецификации в F#, и я хочу скрыть Равняние, 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
[]
abstract Equals : (obj) -> bool
[]
abstract ToString: unit -> string
[]
abstract GetHashCode: unit -> int
[]
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?
Править:
Благодаря справке (см. ниже) я смог решить свою проблему.
Таким образом, .Equals
и .GetHashCode
может быть скрыт через [
[
но это также изменит семантику.
Сокрытие через атрибуты EditorBrowsable не работает.
Единственный способ иметь чистый API и все еще смочь перегрузить методы состоит в том, чтобы сделать этих участников метода статичными.
Получающийся класс может быть найден путем просмотра в моем FSharpSpec проекта.
Рассматриваемый тип может быть найден здесь.
Благодаря всем, кто помог мне решить эту проблему.
Аплодисменты...
В качестве альтернативы вы можете разработать библиотеку, используя альтернативный стиль, используя функции, заключенные в модуль. Это обычный способ написания функционального кода на 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 покажет функции, определенные в модуле, поэтому в этом случае вы не увидите никакого шума.
Повторяю свой ответ от
http://cs.hubfs.net/forums/thread/13317.aspx
В F# вы можете запретить Equals и GetHashCode (и удалить их из intellisense), аннотировав тип атрибутами NoEquality и NoComparison, как показано ниже. Определяемые пользователем методы также можно скрыть из списка intellisense с помощью атрибута Obsolete или атрибута CompilerMessage с IsHidden=true. Не существует способа скрыть методы System.Object GetType и ToString из интенсива F#.
[<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
Я не думаю, что это вообще есть в F #. В конкретном случае .Equals
и .GetHashCode
вы можете сделать их непригодными для использования, поместив атрибут [
в свой тип, но на самом деле это помимо скрытия этих методов имеет семантический эффект.
РЕДАКТИРОВАТЬ
Также стоит упомянуть, что свободные интерфейсы редко используются в F #, поскольку гораздо более идиоматично использовать вместо них комбинаторы и конвейерную обработку. Например, представьте, что мы хотим создать способ создания арифметических выражений. Я думаю, что большинство пользователей F # предпочли бы писать не
let x = Expressions.MakeExpr(1).Add(2).Mul(3).Add(4)
, а
open Expressions
let x =
1
|> makeExpr
|> add 2
|> mul 3
|> add 4
В этом стиле нет необходимости скрывать члены, потому что выражения передаются по конвейеру комбинаторам, а не вызывают методы построителя выражений.