Metódusok
A metódus egy típushoz társított függvény. Az objektumorientált programozásban metódusokat használnak az objektumok és típusok funkcióinak és viselkedésének feltárására és megvalósítására.
Syntax
// 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 ]
Megjegyzések
Az előző szintaxisban a metódusdefiníciók és -definíciók különböző formái láthatók. Hosszabb metódustestekben a sortörés az egyenlőségjelet (=) követi, és a teljes metódustörzs be van húzva.
Az attribútumok bármilyen metódusdeklarációra alkalmazhatók. Ezek megelőzik a metódusdefiníció szintaxisát, és általában külön sorban szerepelnek. További információ: Attribútumok.
A metódusok jelölhetők inline
. További információ: inline
Beágyazott függvények.
A nem beágyazott metódusok rekurzív módon használhatók a típuson belül; nincs szükség a kulcsszó explicit használatára rec
.
Példány metódusai
A példánymetódusok kulcsszóval és önazonosítóval member
vannak deklarálva, amelyet egy pont (.) követ, valamint a metódus neve és paraméterei. A kötésekhez hasonlóan a let
paraméterlista is lehet minta. A metódusparamétereket általában zárójelek közé kell helyeznie egy zárójel formájában, így jelennek meg a metódusok az F#-ban, amikor más .NET-keretrendszer nyelvekben jönnek létre. A curried form (szóközökkel elválasztott paraméterek) azonban szintén gyakoriak, és más minták is támogatottak.
Az alábbi példa egy nem absztrakt példánymetódus definícióját és használatát mutatja be.
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
A példánymódszereken belül ne használja az önazonosítót a let-kötések használatával definiált mezők eléréséhez. Használja az önazonosítót más tagok és tulajdonságok elérésekor.
Statikus metódusok
A kulcsszó static
azt határozza meg, hogy egy metódus példány nélkül hívható meg, és nincs objektumpéldányhoz társítva. Ellenkező esetben a metódusok példánymetenek.
A következő szakaszban látható példa a kulcsszóval deklarált mezőket, a let
member
kulcsszóval deklarált tulajdonságtagokat és a static
kulcsszóval deklarált statikus metódust mutatja be.
Az alábbi példa a statikus metódusok definícióját és használatát mutatja be. Tegyük fel, hogy ezek a metódusdefiníciók az SomeType
előző szakaszban szereplő osztályban találhatók.
static member SomeStaticMethod(a, b, c) =
(a + b + c)
static member SomeOtherStaticMethod(a, b, c) =
SomeType.SomeStaticMethod(a, b, c) * 100
Absztrakt és virtuális metódusok
A kulcsszó abstract
azt jelzi, hogy egy metódus rendelkezik egy virtuális diszpécser ponttal, és lehet, hogy nincs definíciója az osztályban. A virtuális küldési pont egy belsőleg karbantartott függvénytáblában található bejegyzés, amelyet futásidőben használnak a virtuális függvényhívások objektumorientált típusban való kereséséhez. A virtuális küldési mechanizmus a polimorfizmust megvalósító mechanizmus, amely az objektumorientált programozás fontos funkciója. A definíció nélküli legalább egy absztrakt metódussal rendelkező osztály absztrakt osztály, ami azt jelenti, hogy az osztályból nem hozhatók létre példányok. Az absztrakt osztályokról további információt az Absztrakt osztályok című témakörben talál.
Az absztrakt metódus deklarációi nem tartalmaznak metódustörzset. Ehelyett a metódus nevét kettőspont (:) és a metódus típusadakta követi. A metódus típusaláírása megegyezik az IntelliSense által megjelenítettvel, amikor az egérmutatót a Visual Studio Code Editorban egy metódusnév fölé szünetelteti, kivéve a paraméternevek nélkül. A gépi aláírásokat az értelmező is megjeleníti, fsi.exe, amikor interaktívan dolgozik. A metódus típusaadéka a paraméterek típusainak felsorolásával, majd a visszatérési típussal, a megfelelő elválasztó szimbólumokkal. A curried paramétereket a rendszer elkülöníti, ->
a rekordparamétereket pedig a *
. A visszatérési értéket mindig szimbólum választja ->
el az argumentumoktól. A zárójelek összetett paraméterek csoportosítására használhatók, például ha egy függvénytípus paraméter, vagy azt jelzi, hogy egy rekordot a rendszer két paraméter helyett egyetlen paraméterként kezel.
Az absztrakt metódusok alapértelmezett definícióit úgy is megadhatja, hogy hozzáadja a definíciót az osztályhoz, és használja a default
kulcsszót, ahogyan az a jelen témakör szintaxisblokkjában látható. Az ugyanabban az osztályban definiált absztrakt metódus egyenértékű más .NET-keretrendszer nyelvek virtuális metódusával. Függetlenül attól, hogy létezik-e definíció, a abstract
kulcsszó létrehoz egy új küldési pontot az osztály virtuális függvénytáblájában.
Függetlenül attól, hogy egy alaposztály implementálja-e az absztrakt metódusait, a származtatott osztályok absztrakciós módszerek implementálását is biztosíthatják. Ha absztrakt metódust szeretne implementálni egy származtatott osztályban, definiáljon egy metódust, amelynek neve és aláírása azonos a származtatott osztályban, kivéve a kulcsszót vagy default
a kulcsszótoverride
, és adja meg a metódus törzsét. A kulcsszavak override
és default
azt jelenti, pontosan ugyanazt a dolgot. Akkor használja override
, ha az új metódus felülír egy alaposztály-implementációt; akkor használja default
, ha az eredeti absztrakt deklarációval azonos osztályban hoz létre implementációt. Ne használja a kulcsszót abstract
azon a metóduson, amely az alaposztályban absztraktként deklarált metódust implementálja.
Az alábbi példa egy alapértelmezett implementációval rendelkező absztrakt metódust Rotate
mutat be, amely egy .NET-keretrendszer virtuális metódusnak felel meg.
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
Az alábbi példa egy olyan származtatott osztályt mutat be, amely felülír egy alaposztály-metódust. Ebben az esetben a felülbírálás megváltoztatja a viselkedést, így a metódus nem tesz semmit.
type Circle(radius: float) =
inherit Ellipse(radius, radius, 0.0)
// Circles are invariant to rotation, so do nothing.
override this.Rotate(_) = ()
Többszörös szerepű metódusok
A túlterhelt metódusok olyan metódusok, amelyek azonos nevűek egy adott típusban, de eltérő argumentumokkal rendelkeznek. Az F#-ban a választható argumentumok általában túlterhelt metódusok helyett használatosak. A túlterhelt metódusok azonban megengedettek a nyelvben, feltéve, hogy az argumentumok gördült formában vannak, nem pedig curried formában.
Nem kötelező argumentumok
Az F# 4.1-től kezdődően a metódusok alapértelmezett paraméterértékével is rendelkezhet választható argumentumokkal. Ez a C# kóddal való együttműködés megkönnyítését segíti elő. Az alábbi példa a szintaxist mutatja be:
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
Vegye figyelembe, hogy a megadott értéknek DefaultParameterValue
meg kell egyeznie a bemeneti típussal. A fenti mintában ez egy int
. Ha nem egész számot DefaultParameterValue
próbál meg átadni, fordítási hibát eredményez.
Példa: Tulajdonságok és metódusok
Az alábbi példa olyan típust tartalmaz, amely példákat tartalmaz mezőkre, privát függvényekre, tulajdonságokra és statikus metódusokra.
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