Metode

Metode adalah fungsi yang terkait dengan jenis. Di dalam pemrograman berorientasi objek, metode digunakan untuk mengekspos dan mengimplementasikan fungsionalitas dan perilaku objek dan jenis.

Sintaks

// 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 ]

Keterangan

Di dalam sintaks sebelumnya, Anda dapat melihat berbagai bentuk deklarasi dan definisi metode. Di dalam isi metode yang lebih panjang, pemisah baris mengikuti tanda sama dengan (=), dan seluruh isi metode diindentasi.

Atribut dapat diterapkan ke deklarasi metode apa pun. Mereka mendahului sintaks untuk definisi metode, dan biasanya tercantum pada baris yang terpisah. Untuk informasi selengkapnya, lihat Atribut.

Metode dapat ditandai inline. Untuk informasi tentang inline, lihat Fungsi Sebaris.

Metode non-sebaris dapat digunakan secara rekursif dalam jenis; tidak perlu menggunakan kata kunci rec secara eksplisit.

Metode Instans

Metode instans dideklarasikan dengan kata kunci member dan pengidentifikasi-mandiri, diikuti dengan titik (.) dan nama metode dan parameter. Seperti halnya untuk pengikatan let, daftar-parameter dapat berupa pola. Biasanya, Anda mengapit parameter metode dalam tanda kurung dalam bentuk tupel, yang merupakan cara metode muncul di F# ketika dibuat dalam bahasa .NET Framework lainnya. Namun, bentuk curried (parameter yang dipisahkan oleh spasi) juga umum, dan pola lain juga didukung.

Contoh berikut ini mengilustrasikan definisi dan penggunaan metode instans non-abstrak.

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

Dalam metode instans, jangan gunakan pengidentifikasi mandiri untuk mengakses bidang yang ditentukan dengan menggunakan pengikatan let. Gunakan pengidentifikasi mandiri saat mengakses anggota dan properti lain.

Metode Statis

Kata kunci static digunakan untuk menentukan bahwa metode dapat dipanggil tanpa instans dan tidak terkait dengan instans objek. Jika tidak, metode adalah metode instans.

Contoh di bagian berikutnya memperlihatkan bidang yang dideklarasikan dengan kata kunci let, anggota properti yang dideklarasikan dengan kata kunci member, dan metode statis yang dideklarasikan dengan kata kunci static.

Contoh berikut ini mengilustrasikan definisi dan penggunaan metode statis. Asumsikan bahwa definisi metode ini ada di kelas SomeType di bagian sebelumnya.

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

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

Metode Abstrak dan Virtual

Kata kunci abstract menunjukkan bahwa metode memiliki slot pengiriman virtual dan mungkin tidak memiliki definisi di dalam kelas. Slot pengiriman virtual adalah sebuah entri di dalam tabel fungsi yang dikelola secara internal yang digunakan pada run time untuk mencari panggilan fungsi virtual dalam jenis berorientasi-objek. Mekanisme pengiriman virtual adalah mekanisme yang mengimplementasikan polimorfisme, fitur penting dari pemrograman berorientasi-objek. Kelas yang memiliki setidaknya satu metode abstrak tanpa definisi adalah kelas abstrak, yang berarti bahwa tidak ada instans yang dapat dibuat dari kelas tersebut. Untuk informasi selengkapnya tentang kelas abstract, lihat Kelas Abstract.

Deklarasi metode abstrak tidak menyertakan isi metode. Sebaliknya, nama metode diikuti oleh titik dua (:) dan tanda tangan jenis untuk metode. Tanda tangan jenis metode sama dengan yang ditunjukkan oleh IntelliSense saat Anda menjeda penunjuk mouse di atas nama metode di Editor Visual Studio Code, kecuali tanpa nama parameter. Tanda tangan jenis juga ditampilkan oleh penerjemah, fsi.exe, saat Anda bekerja secara interaktif. Tanda tangan jenis metode dibentuk dengan mencantumkan jenis parameter, diikuti dengan jenis pengembalian, dengan simbol pemisah yang sesuai. Parameter curried dipisahkan oleh ->, dan parameter tupel dipisahkan oleh *. Nilai yang dikembalikan selalu dipisahkan dari argumen dengan simbol ->. Parentesis dapat digunakan untuk mengelompokkan parameter yang kompleks, seperti ketika jenis fungsi adalah parameter, atau untuk menunjukkan kapan tupel diperlakukan sebagai parameter tunggal daripada sebagai dua parameter.

Anda juga dapat memberikan definisi default metode abstrak dengan menambahkan definisi ke kelas dan menggunakan kata kunci default, seperti yang ditunjukkan dalam blok sintaks dalam topik ini. Metode abstrak yang memiliki definisi di kelas yang sama setara dengan metode virtual dalam bahasa .NET Framework lainnya. Apakah sebuah definisi ada atau tidak, kata kunci abstract membuat slot pengiriman baru dalam tabel fungsi virtual untuk kelas tersebut.

Terlepas dari apakah kelas dasar mengimplementasikan metode abstraknya, kelas turunan dapat menyediakan implementasi metode abstrak. Untuk mengimplementasikan metode abstrak di kelas turunan, tentukan metode yang memiliki nama dan tanda tangan yang sama di dalam kelas turunan, hanya saja gunakan kata kunci override atau default, dan sediakan isi metode. Kata kunci override dan default artinya sama persis. Gunakan override jika metode baru mengambil alih implementasi kelas dasar; gunakan default saat Anda membuat implementasi di kelas yang sama dengan deklarasi abstrak asli. Jangan gunakan kata kunci abstract pada metode yang mengimplementasikan metode yang dideklarasikan sebagai abstrak di kelas dasar.

Contoh berikut menggambarkan metode abstrak Rotate yang memiliki implementasi default, setara dengan metode virtual .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

Contoh berikut mengilustrasikan kelas turunan yang mengambil alih metode kelas dasar. Dalam hal ini, pengambilalihan mengubah perilaku, sehingga metode tidak melakukan apa pun.

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

Metode Kelebihan Beban

Metode yang kelebihan beban adalah metode yang memiliki nama identik dalam jenis tertentu, tetapi memiliki argumen yang berbeda. Dalam F#, argumen opsional biasanya digunakan alih-alih menggunakan metode yang kelebihan beban. Namun, metode yang kelebihan beban diizinkan dalam bahasa, asalkan argumen dalam bentuk tupel, bukan bentuk curried.

Argumen Opsional

Dimulai dengan F# 4.1, Anda juga dapat memiliki argumen opsional dengan nilai parameter default di dalam metode. Ini untuk membantu memfasilitasi interoperabilitas dengan kode C#. Contoh berikut menunjukkan sintaks:

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

Perhatikan bahwa nilai yang diteruskan untuk DefaultParameterValue harus cocok dengan jenis input. Dalam sampel di atas, ini adalah int. Mencoba meneruskan nilai non-bilangan bulat ke dalam DefaultParameterValue akan mengakibatkan kesalahan kompilasi.

Contoh: Properti dan Metode

Contoh berikut berisi jenis yang memiliki contoh bidang, fungsi privat, properti, dan metode statis.

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

Lihat juga