Arabirimler (F#)
Arabirimler , diğer sınıfların uyguladığı ilgili üye kümelerini belirtir.
Sözdizimi
// 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
Açıklamalar
Arabirim bildirimleri, hiçbir üye uygulanmamış olması dışında sınıf bildirimlerine benzer. Bunun yerine, anahtar sözcüğüyle abstract
gösterildiği gibi tüm üyeler soyut olur. Soyut yöntemler için bir yöntem gövdesi sağlamazsınız. F# bir arabirimde varsayılan yöntem uygulamasını tanımlayamaz, ancak C# tarafından tanımlanan varsayılan uygulamalarla uyumludur. anahtar sözcüğünü default
kullanan varsayılan uygulamalar yalnızca arabirim olmayan bir temel sınıftan devralma sırasında desteklenir.
Arabirimler için varsayılan erişilebilirlik değeridir public
.
İsteğe bağlı olarak normal F# söz dizimini kullanarak her yöntem parametresine bir ad verebilirsiniz:
type ISprintable =
abstract member Print: format: string -> unit
Yukarıdaki ISprintable
örnekte yöntemi, Print
adlı format
türünde string
tek bir parametreye sahiptir.
Arabirimleri uygulamanın iki yolu vardır: nesne ifadelerini kullanarak ve türleri kullanarak. Her iki durumda da tür veya nesne ifadesi, arabirimin soyut yöntemleri için yöntem gövdeleri sağlar. Uygulamalar, arabirimi uygulayan her türe özeldir. Bu nedenle, farklı türlerdeki arabirim yöntemleri birbirinden farklı olabilir.
Basit söz dizimi kullandığınızda, tanımın başlangıcını ve sonunu işaretleyen ve end
anahtar sözcükleri interface
isteğe bağlıdır. Bu anahtar sözcükleri kullanmazsanız, derleyici kullandığınız yapıları analiz ederek türün bir sınıf mı yoksa arabirim mi olduğunu çıkarsamaya çalışır. Bir üye tanımlarsanız veya başka bir sınıf söz dizimi kullanırsanız, tür sınıf olarak yorumlanır.
.NET kodlama stili, tüm arabirimleri büyük I
harfle başlatmaktır.
Birden çok parametreyi iki şekilde belirtebilirsiniz: F#style ve . NET stili. Her ikisi de .NET tüketicileri için aynı şekilde derlenir, ancak F#style F# çağıranları F#style parametre uygulamasını ve kullanmaya zorlar. NET stili, F# çağıranlarını yinelenen bağımsız değişken uygulamasını kullanmaya zorlar.
type INumericFSharp =
abstract Add: x: int -> y: int -> int
type INumericDotNet =
abstract Add: x: int * y: int -> int
Sınıf Türlerini Kullanarak Arabirimleri Uygulama
Aşağıdaki kodda gösterildiği gibi anahtar sözcüğünü, arabirimin adını ve anahtar sözcüğünü ve with
ardından arabirim üyesi tanımlarını kullanarak interface
bir sınıf türünde bir veya daha fazla arabirim uygulayabilirsiniz.
type IPrintable =
abstract member Print: unit -> unit
type SomeClass1(x: int, y: float) =
interface IPrintable with
member this.Print() = printfn "%d %f" x y
Arabirim uygulamaları devralınır, bu nedenle türetilmiş sınıfların bunları yeniden ataması gerekmez.
Arabirim Yöntemlerini Çağırma
Arabirim yöntemleri, arabirimi uygulayan türün herhangi bir nesnesi aracılığıyla değil, yalnızca arabirim aracılığıyla çağrılabilir. Bu nedenle, bu yöntemleri çağırmak için işlecini :>
veya upcast
işlecini kullanarak arabirim türüne yükseltmeniz gerekebilir.
türünde SomeClass
bir nesneniz olduğunda arabirim yöntemini çağırmak için, aşağıdaki kodda gösterildiği gibi nesnesini arabirim türüne yukarı yayınlamalısınız.
let x1 = new SomeClass1(1, 2.0)
(x1 :> IPrintable).Print()
Alternatif olarak, aşağıdaki örnekte olduğu gibi yukarı yayınlayan ve arabirim yöntemini çağıran nesnede bir yöntem bildirilir.
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()
Nesne İfadelerini Kullanarak Arabirimleri Uygulama
Nesne ifadeleri bir arabirim uygulamak için kısa bir yol sağlar. Adlandırılmış bir tür oluşturmanız gerekmediğinde ve herhangi bir ek yöntem olmadan yalnızca arabirim yöntemlerini destekleyen bir nesne istediğinizde kullanışlıdır. Nesne ifadesi aşağıdaki kodda gösterilmiştir.
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()
Arabirim Devralma
Arabirimler bir veya daha fazla temel arabirimden devralabilir.
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
Varsayılan uygulamalarla arabirimleri uygulama
C# aşağıdaki gibi varsayılan uygulamalarla arabirim tanımlamayı destekler:
using System;
namespace CSharp
{
public interface MyDim
{
public int Z => 0;
}
}
Bunlar doğrudan F# ile kullanılabilir:
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}"
herhangi bir sanal üyeyi geçersiz kılmak gibi varsayılan bir uygulamayı ile override
geçersiz kılabilirsiniz.
Varsayılan uygulaması olmayan bir arabirimdeki tüm üyeler yine de açıkça uygulanmalıdır.
Farklı genel örneklemelerde aynı arabirimi uygulama
F# aşağıdaki gibi farklı genel örneklemelerde aynı arabirimin uygulanmasını destekler:
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"