Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de changer d’annuaire.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer d’annuaire.
Les classes abstraites sont des classes qui conservent certains membres ou tous les membres non implémentés, afin que les implémentations puissent être fournies par des classes dérivées.
Syntaxe
// Abstract class syntax.
[<AbstractClass>]
type [ accessibility-modifier ] abstract-class-name =
[ inherit base-class-or-interface-name ]
[ abstract-member-declarations-and-member-definitions ]
// Abstract member syntax.
abstract member member-name : type-signature
Remarques
Dans la programmation orientée objet, une classe abstraite est utilisée comme classe de base d’une hiérarchie et représente les fonctionnalités courantes d’un ensemble diversifié de types d’objets. Comme l’indique le nom « abstrait », les classes abstraites ne correspondent souvent pas directement aux entités concrètes dans le domaine du problème. Toutefois, ils représentent ce que de nombreuses entités concrètes ont en commun.
Les classes abstraites doivent avoir l’attribut AbstractClass . Ils peuvent avoir implémenté et mis en œuvre des membres non implémentés. L’utilisation du terme abstrait lorsqu’il est appliqué à une classe est identique à celui d’autres langages .NET ; Toutefois, l’utilisation du terme abstrait lorsqu’elle est appliquée aux méthodes (et aux propriétés) est un peu différente de celle utilisée dans d’autres langages .NET. Dans F#, lorsqu’une méthode est marquée avec le abstract mot clé, cela indique qu’un membre a une entrée, appelée emplacement de répartition virtuelle, dans la table interne des fonctions virtuelles pour ce type. En d’autres termes, la méthode est virtuelle, même si le virtual mot clé n’est pas utilisé dans F#. Le mot clé abstract est utilisé sur les méthodes virtuelles, que la méthode soit implémentée. La déclaration d’un emplacement de répartition virtuel est distincte de la définition d’une méthode pour cet emplacement de répartition. Par conséquent, l’équivalent F# d’une déclaration et d’une définition de méthode virtuelle dans un autre langage .NET est une combinaison d’une déclaration de méthode abstraite et d’une définition distincte, avec le default mot clé ou le override mot clé. Pour plus d’informations et d’exemples, consultez Méthodes.
Une classe est considérée comme abstraite uniquement s’il existe des méthodes abstraites déclarées, mais non définies. Par conséquent, les classes qui ont des méthodes abstraites ne sont pas nécessairement des classes abstraites. Sauf si une classe a des méthodes abstraites non définies, n’utilisez pas l’attribut AbstractClass .
Dans la syntaxe précédente, le modificateur d’accessibilité peut être public, private ou internal. Pour plus d’informations, consultez Contrôle d’accès.
Comme pour d’autres types, les classes abstraites peuvent avoir une classe de base et une ou plusieurs interfaces de base. Chaque classe de base ou interface apparaît sur une ligne distincte avec le inherit mot clé.
La définition de type d’une classe abstraite peut contenir des membres entièrement définis, mais elle peut également contenir des membres abstraits. La syntaxe des membres abstraits s’affiche séparément dans la syntaxe précédente. Dans cette syntaxe, la signature de type d’un membre est une liste qui contient les types de paramètres dans l’ordre et les types de retour, séparés par -> des jetons et/ou * des jetons appropriés pour les paramètres curried et tupled. La syntaxe des signatures de type membre abstraites est la même que celle utilisée dans les fichiers de signature et affichée par IntelliSense dans Visual Studio Code Editor.
Le code suivant illustre une forme de classe abstraite, qui a deux classes dérivées non abstraites, Square et Circle. L’exemple montre comment utiliser des classes abstraites, des méthodes et des propriétés. Dans l’exemple, la forme de classe abstraite représente les éléments communs des entités concrètes cercle et carré. Les caractéristiques courantes de toutes les formes (dans un système de coordonnées à deux dimensions) sont abstraites dans la classe Shape : la position sur la grille, un angle de rotation et les propriétés de zone et de périmètre. Elles peuvent être remplacées, à l’exception de la position, du comportement dont les formes individuelles ne peuvent pas changer.
La méthode de rotation peut être substituée, comme dans la classe Circle, qui est invariante de rotation en raison de sa symétrie. Ainsi, dans la classe Circle, la méthode de rotation est remplacée par une méthode qui ne fait rien.
// An abstract class that has some methods and properties defined
// and some left abstract.
[<AbstractClass>]
type Shape2D(x0: float, y0: float) =
let mutable x, y = x0, y0
let mutable rotAngle = 0.0
// These properties are not declared abstract. They
// cannot be overriden.
member this.CenterX
with get () = x
and set xval = x <- xval
member this.CenterY
with get () = y
and set yval = y <- yval
// These properties are abstract, and no default implementation
// is provided. Non-abstract derived classes must implement these.
abstract Area: float with get
abstract Perimeter: float with get
abstract Name: string with get
// This method is not declared abstract. It cannot be
// overridden.
member this.Move dx dy =
x <- x + dx
y <- y + dy
// An abstract method that is given a default implementation
// is equivalent to a virtual method in other .NET languages.
// Rotate changes the internal angle of rotation of the square.
// Angle is assumed to be in degrees.
abstract member Rotate: float -> unit
default this.Rotate(angle) = rotAngle <- rotAngle + angle
type Square(x, y, sideLengthIn) =
inherit Shape2D(x, y)
member this.SideLength = sideLengthIn
override this.Area = this.SideLength * this.SideLength
override this.Perimeter = this.SideLength * 4.
override this.Name = "Square"
type Circle(x, y, radius) =
inherit Shape2D(x, y)
let PI = 3.141592654
member this.Radius = radius
override this.Area = PI * this.Radius * this.Radius
override this.Perimeter = 2. * PI * this.Radius
// Rotating a circle does nothing, so use the wildcard
// character to discard the unused argument and
// evaluate to unit.
override this.Rotate(_) = ()
override this.Name = "Circle"
let square1 = new Square(0.0, 0.0, 10.0)
let circle1 = new Circle(0.0, 0.0, 5.0)
circle1.CenterX <- 1.0
circle1.CenterY <- -2.0
square1.Move -1.0 2.0
square1.Rotate 45.0
circle1.Rotate 45.0
printfn "Perimeter of square with side length %f is %f, %f" (square1.SideLength) (square1.Area) (square1.Perimeter)
printfn "Circumference of circle with radius %f is %f, %f" (circle1.Radius) (circle1.Area) (circle1.Perimeter)
let shapeList: list<Shape2D> = [ (square1 :> Shape2D); (circle1 :> Shape2D) ]
List.iter (fun (elem: Shape2D) -> printfn "Area of %s: %f" (elem.Name) (elem.Area)) shapeList
Output:
Perimeter of square with side length 10.000000 is 40.000000
Circumference of circle with radius 5.000000 is 31.415927
Area of Square: 100.000000
Area of Circle: 78.539816