Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az interfészek olyan kapcsolódó tagcsoportokat határoznak meg, amelyeket más osztályok implementálnak.
Szemantika
// 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
Megjegyzések
A felületi deklarációk az osztálydeklarációkhoz hasonlítanak, azzal a kivételével, hogy nincsenek tagok implementálva. Ehelyett az összes tag absztrakt, ahogy azt a kulcsszó abstractis jelzi. Az absztrakt metódusokhoz nem ad meg metódustörzset. Az F# nem tud alapértelmezett metódus-implementációt definiálni egy felületen, de kompatibilis a C# által definiált alapértelmezett implementációkkal. A kulcsszót használó default alapértelmezett implementációk csak akkor támogatottak, ha nem felületi alaposztályból örökölnek.
A felületek alapértelmezett akadálymentessége a következő public: .
Az egyes metódusparaméterek megadhatnak egy nevet normál F# szintaxissal:
type ISprintable =
abstract member Print: format: string -> unit
A fenti példában a ISprintable metódusnak egyetlen paramétere van a típusnak Print a nevévelstring.format
Az interfészek kétféleképpen implementálhatók: objektumkifejezések használatával és típusok használatával. A típus- vagy objektumkifejezés mindkét esetben metódustesteket biztosít a felület absztrakt metódusaihoz. Az implementációk minden olyan típusra vonatkoznak, amely implementálja az interfészt. Ezért a különböző típusok felületi metódusai eltérhetnek egymástól.
A definíció kezdetét és végét jelző kulcsszavak interfaceendnem kötelezőek, ha egyszerűsített szintaxist használ. Ha nem használja ezeket a kulcsszavakat, a fordító a használt szerkezetek elemzésével megpróbálja megállapítani, hogy a típus osztály vagy felület-e. Ha tagot határoz meg, vagy más osztályszintaxist használ, a rendszer osztályként értelmezi a típust.
A .NET kódolási stílusa az, hogy az összes felületet nagybetűvel Ikezdje.
Kétféleképpen adhat meg több paramétert: F#-style és . NET-stílus. Mindkettő ugyanúgy fog összeállni a .NET-felhasználók számára, de az F#-stílus kényszeríti az F#-hívókat az F#-stílusú paraméteralkalmazás és a . A NET-stílus kényszeríti az F#-hívókat a csatolt argumentumalkalmazás használatára.
type INumericFSharp =
abstract Add: x: int -> y: int -> int
type INumericDotNet =
abstract Add: x: int * y: int -> int
Interfészek implementálása osztálytípusok használatával
Egy vagy több illesztőt egy osztálytípusban a kulcsszóval, az interface interfész nevével és a with kulcsszóval, majd a felülettagdefiníciókkal valósíthat meg, ahogyan az az alábbi kódban is látható.
type IPrintable =
abstract member Print: unit -> unit
type SomeClass1(x: int, y: float) =
interface IPrintable with
member this.Print() = printfn "%d %f" x y
A felületi implementációk öröklődnek, így a származtatott osztályoknak nem kell újrakonfigurálnia őket.
Üres vagy jelölőfelületek definiálása
Az üres illesztők, más néven jelölőillesztők különböző típusok azonosítására használhatók anélkül, hogy konkrét viselkedésre lenne szükség. Ezeknek az interfészeknek nincsenek tagjai, és kategorizálási célokra használhatók a típusok megjelölésére vagy címkézésére.
Üres felületet definiálhat a interface end szintaxis használatával:
// 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
A fenti IMarker példában üres felületként van definiálva.
MyClass Ezt az interfészt is MyRecord implementálhatja anélkül, hogy bármilyen metódus implementációt kellene biztosítania, mivel az interfésznek nincsenek tagjai. Ez lehetővé teszi, hogy a felülettípussal azonosítsa és közösen használja ezeket a típusokat.
Hívófelület metódusai
Az interfészmetódusok csak az interfészen keresztül hívhatók meg, az interfészt megvalósító objektumon keresztül nem. Így előfordulhat, hogy a metódusok meghívásához az operátort vagy az :>upcast operátort kell a felülettípusra felcímkenni.
A felület metódusának meghívásához, ha rendelkezik egy típusú SomeClassobjektummal, az objektumot a felület típusára kell felcímkenni, ahogyan az az alábbi kódban is látható.
let x1 = new SomeClass1(1, 2.0)
(x1 :> IPrintable).Print()
Másik lehetőségként deklarálhat egy metódust azon az objektumon, amely az illesztőmetódusra hivatkozik és meghívja, ahogyan az alábbi példában is látható.
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()
Felületek implementálása objektumkifejezések használatával
Az objektumkifejezések rövid módot biztosítanak egy felület implementálására. Ezek akkor hasznosak, ha nem kell névvel ellátott típust létrehoznia, és csak olyan objektumot szeretne, amely támogatja az interfészmetódusokat további metódusok nélkül. Az objektumkifejezéseket az alábbi kód szemlélteti.
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()
Interfész öröklése
Az illesztők egy vagy több alapillesztőtől örökölhetnek.
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
Interfészek implementálása alapértelmezett implementációkkal
A C# támogatja az alapértelmezett implementációkkal rendelkező felületek meghatározását, például:
using System;
namespace CSharp
{
public interface MyDim
{
public int Z => 0;
}
}
Ezek közvetlenül az F#-ból fogyaszthatók:
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}"
Az alapértelmezett implementációk felülbírálhatók például bármely virtuális tag felülbírálásával override.
A felület azon tagjait, amelyek nem rendelkeznek alapértelmezett implementációval, explicit módon kell implementálnunk.
Ugyanazon felület implementálása különböző általános példányokon
Az F# támogatja ugyanazt a felületet különböző általános példányokon, például:
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"