Partager via


Méthodes

Une méthode est une fonction associée à un type. Dans la programmation orientée objet, les méthodes sont utilisées pour exposer et implémenter les fonctionnalités et le comportement des objets et des types.

Syntaxe

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

Notes

Dans la syntaxe précédente, vous pouvez voir les différentes formes de déclarations et de définitions de méthode. Dans les corps de méthode plus longs, un saut de ligne suit le signe égal (=), et l’ensemble du corps de la méthode est mis en retrait.

Les attributs peuvent être appliqués à n’importe quelle déclaration de méthode. Ils précèdent la syntaxe d’une définition de méthode et sont généralement répertoriés sur une ligne distincte. Pour plus d’informations, consultez Attributs.

Les méthodes peuvent être marquées inline. Pour plus d’informations sur inline, consultez Fonctions inline.

Les méthodes non inline peuvent être utilisées de manière récursive dans le type ; il n’est pas nécessaire d’utiliser explicitement le mot clé rec.

Méthodes d’instance

Les méthodes d’instance sont déclarées avec le mot clé member et un auto-identificateur, suivis d’un point (.) et du nom et des paramètres de la méthode. Comme c’est le cas pour les liaisons let, la liste de paramètres peut être un modèle. En règle générale, vous placez les paramètres de méthode entre parenthèses dans un tuple, ce qui correspond à la façon dont les méthodes apparaissent dans F# lorsqu’elles sont créées dans d’autres langages .NET Framework. Toutefois, la forme curryfiée (paramètres séparés par des espaces) est également courante, et d’autres modèles sont également pris en charge.

L’exemple suivant illustre la définition et l’utilisation d’une méthode d’instance non abstraite.

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

Dans les méthodes d’instance, n’utilisez pas l’identificateur automatique pour accéder aux champs définis à l’aide de liaisons let. Utilisez l’auto-identificateur lors de l’accès à d’autres membres et propriétés.

Méthodes statiques

Le mot clé static est utilisé pour spécifier qu’une méthode peut être appelée sans instance et n’est pas associée à un objet d’instance. Sinon, les méthodes sont des méthodes d’instance.

L’exemple de la section suivante montre les champs déclarés avec le mot clé let, les membres de propriété déclarés avec le mot clé member et une méthode statique déclarée avec le mot clé static.

L’exemple suivant illustre la définition et l’utilisation de méthodes statiques. Supposons que ces définitions de méthode se trouvent dans la classe SomeType dans la section précédente.

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

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

Méthodes abstraites et virtuelles

Le mot clé abstract indique qu’une méthode a un emplacement de dispatch virtuel et n’a peut-être pas de définition dans la classe. Un emplacement de dispatch virtuel est une entrée dans une table de fonctions gérée en interne qui est utilisée au moment de l’exécution pour rechercher des appels de fonctions virtuelles dans un type orienté objet. Le mécanisme de dispatch virtuel est le mécanisme qui implémente le polymorphisme, une fonctionnalité importante de la programmation orientée objet. Une classe qui a au moins une méthode abstraite sans définition est une classe abstraite, ce qui signifie qu’aucune instance de cette classe ne peut être créée. Pour plus d’informations sur les classes abstraites, consultez Classes abstraites.

Les déclarations de méthode abstraites n’incluent pas de corps de méthode. Au lieu de cela, le nom de la méthode est suivi d’un signe deux-points (:) et d’une signature de type pour la méthode. La signature de type d’une méthode est identique à celle affichée par IntelliSense lorsque vous placez le pointeur de la souris sur un nom de méthode dans Visual Studio Code Editor, sauf qu’il n’y a pas de noms de paramètre. Les signatures de type sont également affichées par l’interpréteur, fsi.exe, lorsque vous travaillez de manière interactive. La signature de type d’une méthode est formée en répertoriant les types des paramètres, suivis du type de retour, avec les symboles de séparation appropriés. Les paramètres curryfiés sont séparés par ->, et les paramètres de tuple sont séparés par *. La valeur de retour est toujours séparée des arguments par un symbole ->. Les parenthèses peuvent être utilisées pour regrouper des paramètres complexes, par exemple lorsqu’un type de fonction est un paramètre, ou pour indiquer quand un tuple est traité comme un paramètre unique plutôt que comme deux paramètres.

Vous pouvez également donner des définitions par défaut de méthodes abstraites en ajoutant la définition à la classe et en utilisant le mot clé default, comme indiqué dans le bloc de syntaxe de cette rubrique. Une méthode abstraite qui a une définition dans la même classe équivaut à une méthode virtuelle dans d’autres langages .NET Framework. Qu’une définition existe ou non, le mot clé abstract crée un emplacement de dispatch dans la table de fonctions virtuelles de la classe.

Qu’une classe de base implémente ou non ses méthodes abstraites, les classes dérivées peuvent fournir des implémentations des méthodes abstraites. Pour implémenter une méthode abstraite dans une classe dérivée, définissez une méthode qui a le même nom et la même signature dans la classe dérivée, mais utilisez le mot clé override ou default et fournissez le corps de la méthode. Les mots clés override et default signifient exactement la même chose. Utilisez override si la nouvelle méthode remplace une implémentation de classe de base ; utilisez default lorsque vous créez une implémentation dans la même classe que la déclaration abstraite d’origine. N’utilisez pas le mot clé abstract sur la méthode qui implémente la méthode déclarée abstraite dans la classe de base.

L’exemple suivant illustre une méthode abstraite Rotate qui a une implémentation par défaut, l’équivalent d’une méthode virtuelle .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

L’exemple suivant illustre une classe dérivée qui remplace une méthode de classe de base. Dans ce cas, le remplacement modifie le comportement afin que la méthode ne fasse rien.

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

Méthodes surchargées

Les méthodes surchargées sont des méthodes qui ont des noms identiques dans un type donné, mais qui ont des arguments différents. En F#, des arguments facultatifs sont généralement utilisés à la place des méthodes surchargées. Toutefois, les méthodes surchargées sont autorisées dans le langage, à condition que les arguments soient sous forme de tuple et non de forme curryfiée.

Arguments facultatifs

À compter de F# 4.1, vous pouvez également avoir des arguments facultatifs avec une valeur de paramètre par défaut dans les méthodes. Cela permet de faciliter l’interopérabilité avec le code C#. L’exemple suivant illustre la syntaxe :

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

Notez que la valeur passée pour DefaultParameterValue doit correspondre au type d’entrée. Dans l’exemple ci-dessus, il s’agit d’un int. Une tentative de transmission d’une valeur non entière dans DefaultParameterValue entraînerait une erreur de compilation.

Exemple : Propriétés et méthodes

L’exemple suivant contient un type qui contient des exemples de champs, de fonctions privées, de propriétés et d’une méthode statique.

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

Voir aussi