Методы

Метод — это функция, которая связана с типом. В объектно-ориентированном программировании методы используются для предоставления и реализации функциональных возможностей и поведения объектов и типов.

Синтаксис

// Instance method definition.
[ attributes ]
member [inline] self-identifier.method-name parameter-list [ : return-type ] =
    method-body

// Static method definition.
[ attributes ]
static member [inline] method-name parameter-list [ : return-type ] =
    method-body

// Abstract method declaration or virtual dispatch slot.
[ attributes ]
abstract member method-name : type-signature

// Virtual method declaration and default implementation.
[ attributes ]
abstract member method-name : type-signature
[ attributes ]
default self-identifier.method-name parameter-list [ : return-type ] =
    method-body

// Override of inherited virtual method.
[ attributes ]
override self-identifier.method-name parameter-list [ : return-type ] =
    method-body

// Optional and DefaultParameterValue attributes on input parameters
[ attributes ]
[ modifier ] member [inline] self-identifier.method-name ([<Optional; DefaultParameterValue( default-value )>] input) [ : return-type ]

Remarks

В предыдущем синтаксисе можно увидеть различные формы объявлений и определений методов. В более длинных теле метода разрыв строки следует за знаком равенства (=), а весь текст метода — с отступом.

Атрибуты могут применяться к любому объявлению метода. Они предшествуют синтаксису определения метода и обычно перечисляются в отдельной строке. Дополнительные сведения см. в разделе Атрибуты.

Методы могут быть помечены как inline . Сведения о inline см. в статье Встраиваемые функции.

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

Методы экземпляра

Методы экземпляра объявляются с помощью member ключевого слова и идентификатора Self, за которым следует точка (.), а также имя и параметры метода. Как и в случае с let привязками, параметр-List может быть шаблоном. как правило, параметры метода заключаются в круглые скобки в форме кортежа, то есть методы отображаются в F #, когда они создаются на других языках платформа .NET Framework. Однако также часто встречается каррированных формы (параметры, разделенные пробелами), а также поддерживаются и другие шаблоны.

В следующем примере показано определение и использование неабстрактного метода экземпляра.

type SomeType(factor0: int) =
   let factor = factor0
   member this.SomeMethod(a, b, c) =
      (a + b + c) * factor

   member this.SomeOtherMethod(a, b, c) =
      this.SomeMethod(a, b, c) * factor

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

Статические методы

Ключевое слово static используется для указания того, что метод может быть вызван без экземпляра и не связан с экземпляром объекта. В противном случае методы являются методами экземпляра.

В примере в следующем разделе показаны поля, объявленные с помощью let ключевого слова, члены свойств, объявленные с помощью member ключевого слова, и статический метод, объявленный с static ключевым словом.

В следующем примере показано определение и использование статических методов. Предположим, что эти определения методов находятся в SomeType классе в предыдущем разделе.

static member SomeStaticMethod(a, b, c) =
   (a + b + c)

static member SomeOtherStaticMethod(a, b, c) =
   SomeType.SomeStaticMethod(a, b, c) * 100

Абстрактные и виртуальные методы

Ключевое слово abstract указывает, что метод имеет виртуальный слот диспетчеризации и может не иметь определения в классе. Виртуальный слот диспетчеризации — это запись во внутренней таблице функций, которая используется во время выполнения для поиска вызовов виртуальных функций в объектно-ориентированном типе. Виртуальный механизм диспетчеризации — это механизм, который реализует полиморфизм, важный компонент объектно-ориентированного программирования. Класс, имеющий по крайней мере один абстрактный метод без определения, является абстрактным классом, что означает, что экземпляры этого класса создавать нельзя. Дополнительные сведения о абстрактных классах см. в разделе абстрактные классы.

Объявления абстрактных методов не включают тело метода. Вместо этого за именем метода следует двоеточие (:) и сигнатура типа для метода. сигнатура типа метода такая же, как и при использовании IntelliSense при наведении указателя мыши на имя метода в редакторе Visual Studio Code, за исключением случаев, когда имена параметров не указаны. Сигнатуры типов также отображаются интерпретатором fsi.exe при работе в интерактивном режиме. Сигнатура типа метода формируется путем перечисления типов параметров, за которыми следует возвращаемый тип с соответствующими символами-разделителями. Перекаррированных параметров разделяются друг от друга, -> а параметры кортежа разделяются * . Возвращаемое значение всегда отделяется от аргументов -> символом. Круглые скобки можно использовать для группирования сложных параметров, например, если тип функции является параметром или чтобы указать, когда кортеж обрабатывается как один параметр, а не как два параметра.

Можно также предоставить определения абстрактных методов по умолчанию, добавив определение в класс и используя default ключевое слово, как показано в блоке синтаксиса в этом разделе. абстрактный метод, имеющий определение в том же классе, эквивалентен виртуальному методу на других языках платформа .NET Framework. Независимо от того, существует ли определение, abstract ключевое слово создает новый слот диспетчеризации в таблице виртуальной функции для класса.

Независимо от того, реализует ли базовый класс его абстрактные методы, производные классы могут предоставлять реализации абстрактных методов. Чтобы реализовать абстрактный метод в производном классе, определите метод с тем же именем и сигнатурой в производном классе, за исключением использования override default ключевого слова или и предоставления тела метода. Ключевые слова override и default означают то же самое. Используйте override , если новый метод переопределяет реализацию базового класса; используйте default при создании реализации в том же классе, что и исходное абстрактное объявление. Не используйте abstract ключевое слово в методе, который реализует метод, объявленный абстрактным в базовом классе.

в следующем примере показан абстрактный метод Rotate , имеющий реализацию по умолчанию, эквивалентный виртуальному методу платформа .NET Framework.

type Ellipse(a0 : float, b0 : float, theta0 : float) =
    let mutable axis1 = a0
    let mutable axis2 = b0
    let mutable rotAngle = theta0
    abstract member Rotate: float -> unit
    default this.Rotate(delta : float) = rotAngle <- rotAngle + delta

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

type Circle(radius : float) =
    inherit Ellipse(radius, radius, 0.0)
     // Circles are invariant to rotation, so do nothing.
    override this.Rotate(_) = ()

Перегруженные методы

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

Необязательные аргументы

Начиная с F # 4,1, можно также иметь необязательные аргументы со значением параметра по умолчанию в методах. Это помогает упростить взаимодействие с кодом C#. Следующий пример демонстрирует синтаксис:

// A class with a method M, which takes in an optional integer argument.
type C() =
    _.M([<Optional; DefaultParameterValue(12)>] i) = i + 1

Обратите внимание, что значение, передаваемое для DefaultParameterValue , должно соответствовать типу входных данных. В приведенном выше примере это int . Попытка передать нецелочисленное значение в вызовет DefaultParameterValue ошибку компиляции.

Пример: свойства и методы

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

type RectangleXY(x1 : float, y1: float, x2: float, y2: float) =
    // Field definitions.
    let height = y2 - y1
    let width = x2 - x1
    let area = height * width
    // Private functions.
    static let maxFloat (x: float) (y: float) =
      if x >= y then x else y
    static let minFloat (x: float) (y: float) =
      if x <= y then x else y
    // Properties.
    // Here, "this" is used as the self identifier,
    // but it can be any identifier.
    member this.X1 = x1
    member this.Y1 = y1
    member this.X2 = x2
    member this.Y2 = y2
    // A static method.
    static member intersection(rect1 : RectangleXY, rect2 : RectangleXY) =
       let x1 = maxFloat rect1.X1 rect2.X1
       let y1 = maxFloat rect1.Y1 rect2.Y1
       let x2 = minFloat rect1.X2 rect2.X2
       let y2 = minFloat rect1.Y2 rect2.Y2
       let result : RectangleXY option =
         if ( x2 > x1 && y2 > y1) then
           Some (RectangleXY(x1, y1, x2, y2))
         else
           None
       result

// Test code.
let testIntersection =
    let r1 = RectangleXY(10.0, 10.0, 20.0, 20.0)
    let r2 = RectangleXY(15.0, 15.0, 25.0, 25.0)
    let r3 : RectangleXY option = RectangleXY.intersection(r1, r2)
    match r3 with
    | Some(r3) -> printfn "Intersection rectangle: %f %f %f %f" r3.X1 r3.Y1 r3.X2 r3.Y2
    | None -> printfn "No intersection found."

testIntersection

См. также