Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Antarmuka menentukan set anggota terkait yang diterapkan kelas lain.
Sintaksis
// Interface declaration:
[ attributes ]
type [accessibility-modifier] interface-name =
[ interface ] [ inherit base-interface-name ...]
abstract member1 : [ argument-types1 -> ] return-type1
abstract member2 : [ argument-types2 -> ] return-type2
...
[ end ]
// Implementing, inside a class type definition:
interface interface-name with
member self-identifier.member1argument-list = method-body1
member self-identifier.member2argument-list = method-body2
// Implementing, by using an object expression:
[ attributes ]
let class-name (argument-list) =
{ new interface-name with
member self-identifier.member1argument-list = method-body1
member self-identifier.member2argument-list = method-body2
[ base-interface-definitions ]
}
member-list
Komentar
Deklarasi antarmuka menyerupai deklarasi kelas kecuali bahwa tidak ada anggota yang diimplementasikan. Sebaliknya, semua anggota abstrak, seperti yang ditunjukkan oleh kata kunci abstract. Anda tidak menyediakan isi metode untuk metode abstrak. F# tidak dapat menentukan implementasi metode default pada antarmuka, tetapi kompatibel dengan implementasi default yang ditentukan oleh C#. Implementasi default menggunakan default kata kunci hanya didukung saat mewarisi dari kelas dasar non-antarmuka.
Aksesibilitas default untuk antarmuka adalah public.
Anda dapat secara opsional memberi setiap parameter metode nama menggunakan sintaks F# normal:
type ISprintable =
abstract member Print: format: string -> unit
Dalam contoh di atas ISprintable , Print metode memiliki parameter tunggal dari jenis string dengan nama format.
Ada dua cara untuk menerapkan antarmuka: dengan menggunakan ekspresi objek, dan dengan menggunakan jenis. Dalam kedua kasus, jenis atau ekspresi objek menyediakan badan metode untuk metode abstrak antarmuka. Implementasi khusus untuk setiap jenis yang mengimplementasikan antarmuka. Oleh karena itu, metode antarmuka pada berbagai jenis mungkin berbeda satu sama lain.
Kata kunci interface dan end, yang menandai awal dan akhir definisi, bersifat opsional saat Anda menggunakan sintaks ringan. Jika Anda tidak menggunakan kata kunci ini, pengkompilasi mencoba menyimpulkan apakah jenisnya adalah kelas atau antarmuka dengan menganalisis konstruksi yang Anda gunakan. Jika Anda menentukan anggota atau menggunakan sintaks kelas lain, jenis ditafsirkan sebagai kelas.
Gaya pengodian .NET adalah memulai semua antarmuka dengan modal I.
Anda dapat menentukan beberapa parameter dengan dua cara: F#-style dan . Gaya NET. Keduanya akan mengkompilasi cara yang sama untuk konsumen .NET, tetapi F#-style akan memaksa pemanggil F# untuk menggunakan aplikasi parameter F#-style dan . Gaya NET akan memaksa pemanggil F# untuk menggunakan aplikasi argumen yang disetel.
type INumericFSharp =
abstract Add: x: int -> y: int -> int
type INumericDotNet =
abstract Add: x: int * y: int -> int
Menerapkan Antarmuka dengan Menggunakan Jenis Kelas
Anda dapat menerapkan satu atau beberapa antarmuka dalam jenis kelas dengan menggunakan interface kata kunci, nama antarmuka, dan with kata kunci, diikuti oleh definisi anggota antarmuka, seperti yang ditunjukkan dalam kode berikut.
type IPrintable =
abstract member Print: unit -> unit
type SomeClass1(x: int, y: float) =
interface IPrintable with
member this.Print() = printfn "%d %f" x y
Implementasi antarmuka diwariskan, sehingga kelas turunan apa pun tidak perlu melengkapinya kembali.
Menentukan antarmuka kosong atau penanda
Antarmuka kosong, juga dikenal sebagai antarmuka penanda, dapat digunakan untuk mengidentifikasi sekumpulan jenis tanpa memerlukan perilaku tertentu. Antarmuka ini tidak memiliki anggota dan berfungsi sebagai cara untuk menandai atau menandai jenis untuk tujuan kategorisasi.
Anda menentukan antarmuka kosong menggunakan interface end sintaks:
// Define an empty interface (also known as a marker interface)
type IMarker =
interface end
// Implement the empty interface in a record type
type MyRecord =
{ Name: string }
interface IMarker
// Implement the empty interface in a class type
type MyClass(value: int) =
member _.Value = value
interface IMarker
Dalam contoh di atas, IMarker didefinisikan sebagai antarmuka kosong. Baik MyRecord dan MyClass terapkan antarmuka ini tanpa perlu menyediakan implementasi metode apa pun, karena antarmuka tidak memiliki anggota. Ini memungkinkan Anda menggunakan jenis antarmuka untuk mengidentifikasi dan bekerja dengan jenis ini dengan cara yang sama.
Metode Antarmuka Panggilan
Metode antarmuka hanya dapat dipanggil melalui antarmuka, bukan melalui objek jenis apa pun yang mengimplementasikan antarmuka. Dengan demikian, Anda mungkin harus meningkatkan ke jenis antarmuka dengan menggunakan :> operator atau upcast operator untuk memanggil metode ini.
Untuk memanggil metode antarmuka saat Anda memiliki objek jenis SomeClass, Anda harus memperkirakan objek ke jenis antarmuka, seperti yang ditunjukkan dalam kode berikut.
let x1 = new SomeClass1(1, 2.0)
(x1 :> IPrintable).Print()
Alternatifnya adalah mendeklarasikan metode pada objek yang meningkatkan dan memanggil metode antarmuka, seperti dalam contoh berikut.
type SomeClass2(x: int, y: float) =
member this.Print() = (this :> IPrintable).Print()
interface IPrintable with
member this.Print() = printfn "%d %f" x y
let x2 = new SomeClass2(1, 2.0)
x2.Print()
Menerapkan Antarmuka dengan Menggunakan Ekspresi Objek
Ekspresi objek menyediakan cara singkat untuk mengimplementasikan antarmuka. Ini berguna ketika Anda tidak perlu membuat jenis bernama, dan Anda hanya ingin objek yang mendukung metode antarmuka, tanpa metode tambahan. Ekspresi objek diilustrasikan dalam kode berikut.
let makePrintable (x: int, y: float) =
{ new IPrintable with
member this.Print() = printfn "%d %f" x y }
let x3 = makePrintable (1, 2.0)
x3.Print()
Pewarisan Antarmuka
Antarmuka dapat mewarisi dari satu atau beberapa antarmuka dasar.
type Interface1 =
abstract member Method1: int -> int
type Interface2 =
abstract member Method2: int -> int
type Interface3 =
inherit Interface1
inherit Interface2
abstract member Method3: int -> int
type MyClass() =
interface Interface3 with
member this.Method1(n) = 2 * n
member this.Method2(n) = n + 100
member this.Method3(n) = n / 10
Menerapkan antarmuka dengan implementasi default
C# mendukung penentuan antarmuka dengan implementasi default, seperti:
using System;
namespace CSharp
{
public interface MyDim
{
public int Z => 0;
}
}
Ini dapat dikonsumsi langsung dari F#:
open CSharp
// You can implement the interface via a class
type MyType() =
member _.M() = ()
interface MyDim
let md = MyType() :> MyDim
printfn $"DIM from C#: %d{md.Z}"
// You can also implement it via an object expression
let md' = { new MyDim }
printfn $"DIM from C# but via Object Expression: %d{md'.Z}"
Anda dapat mengambil alih implementasi default dengan override, seperti mengambil alih anggota virtual apa pun.
Setiap anggota dalam antarmuka yang tidak memiliki implementasi default masih harus diimplementasikan secara eksplisit.
Menerapkan antarmuka yang sama pada instansiasi generik yang berbeda
F# mendukung penerapan antarmuka yang sama pada instansiasi generik yang berbeda seperti:
type IA<'T> =
abstract member Get : unit -> 'T
type MyClass() =
interface IA<int> with
member x.Get() = 1
interface IA<string> with
member x.Get() = "hello"
let mc = MyClass()
let iaInt = mc :> IA<int>
let iaString = mc :> IA<string>
iaInt.Get() // 1
iaString.Get() // "hello"