Clases abstractasAbstract Classes

Las clases abstractas son clases que dejan algunos o todos los miembros no implementados, de modo que las implementaciones pueden ser proporcionadas por clases derivadas.Abstract classes are classes that leave some or all members unimplemented, so that implementations can be provided by derived classes.

SintaxisSyntax

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

ComentariosRemarks

En la programación orientada a objetos, una clase abstracta se utiliza como una clase base de una jerarquía y representa la funcionalidad común de un conjunto diverso de tipos de objeto.In object-oriented programming, an abstract class is used as a base class of a hierarchy, and represents common functionality of a diverse set of object types. Como el nombre "abstract" implica, las clases abstractas no suelen corresponder directamente con entidades concretas del dominio del problema.As the name "abstract" implies, abstract classes often do not correspond directly onto concrete entities in the problem domain. Sin embargo, representan las distintas entidades concretas que tienen en común.However, they do represent what many different concrete entities have in common.

Las clases abstractas deben AbstractClass tener el atributo.Abstract classes must have the AbstractClass attribute. Pueden tener miembros implementados y no implementados.They can have implemented and unimplemented members. El uso del término abstracto cuando se aplica a una clase es igual que en otros lenguajes .net; sin embargo, el uso del término abstracto cuando se aplica a métodos (y propiedades) es un poco F# diferente en respecto a su uso en otros lenguajes .net.The use of the term abstract when applied to a class is the same as in other .NET languages; however, the use of the term abstract when applied to methods (and properties) is a little different in F# from its use in other .NET languages. En F#, cuando un método se marca con la abstract palabra clave, indica que un miembro tiene una entrada, conocida como ranura de envío virtual, en la tabla interna de funciones virtuales para ese tipo.In F#, when a method is marked with the abstract keyword, this indicates that a member has an entry, known as a virtual dispatch slot, in the internal table of virtual functions for that type. En otras palabras, el método es virtual, aunque la virtual palabra clave no se usa en F# el lenguaje.In other words, the method is virtual, although the virtual keyword is not used in the F# language. La palabra abstract clave se usa en métodos virtuales independientemente de si se implementa el método.The keyword abstract is used on virtual methods regardless of whether the method is implemented. La declaración de una ranura de envío virtual es independiente de la definición de un método para esa ranura de envío.The declaration of a virtual dispatch slot is separate from the definition of a method for that dispatch slot. Por lo tanto F# , el equivalente de una declaración y definición de método virtual en otro lenguaje .net es una combinación de una declaración de método abstracto y una definición independiente default , con la override palabra clave o la palabra clave.Therefore, the F# equivalent of a virtual method declaration and definition in another .NET language is a combination of both an abstract method declaration and a separate definition, with either the default keyword or the override keyword. Para obtener más información y ejemplos, vea métodos.For more information and examples, see Methods.

Una clase se considera abstracta solo si hay métodos abstractos que se declaran pero no se definen.A class is considered abstract only if there are abstract methods that are declared but not defined. Por lo tanto, las clases que tienen métodos abstractos no son necesariamente clases abstractas.Therefore, classes that have abstract methods are not necessarily abstract classes. A menos que una clase tenga métodos abstractos sin definir, no use el atributo AbstractClass .Unless a class has undefined abstract methods, do not use the AbstractClass attribute.

En la sintaxis anterior, el modificador de accesibilidad puede publicser private , internalo.In the previous syntax, accessibility-modifier can be public, private or internal. Para más información, vea Access Control (Control de acceso).For more information, see Access Control.

Como con otros tipos, las clases abstractas pueden tener una clase base y una o varias interfaces base.As with other types, abstract classes can have a base class and one or more base interfaces. Cada clase base o interfaz aparece en una línea independiente junto con la inherit palabra clave.Each base class or interface appears on a separate line together with the inherit keyword.

La definición de tipo de una clase abstracta puede contener miembros totalmente definidos, pero también puede contener miembros abstractos.The type definition of an abstract class can contain fully defined members, but it can also contain abstract members. La sintaxis de los miembros abstractos se muestra por separado en la sintaxis anterior.The syntax for abstract members is shown separately in the previous syntax. En esta sintaxis, la signatura de tipo de un miembro es una lista que contiene los tipos de parámetro en orden y los tipos de valor -> devuelto, separados por * tokens o tokens, según corresponda para los parámetros currificados y de tupla.In this syntax, the type signature of a member is a list that contains the parameter types in order and the return types, separated by -> tokens and/or * tokens as appropriate for curried and tupled parameters. La sintaxis de las signaturas de tipo de miembro abstracto es la misma que la que se usa en los archivos de signatura y que se muestra en IntelliSense en el editor de Visual Studio Code.The syntax for abstract member type signatures is the same as that used in signature files and that shown by IntelliSense in the Visual Studio Code Editor.

En el código siguiente se muestra una forma de clase abstracta, que tiene dos clases derivadas no abstractas, Square y Circle.The following code illustrates an abstract class Shape, which has two non-abstract derived classes, Square and Circle. En el ejemplo se muestra cómo usar clases, métodos y propiedades abstractos.The example shows how to use abstract classes, methods, and properties. En el ejemplo, la forma de clase abstracta representa los elementos comunes del círculo y el cuadrado de las entidades concretas.In the example, the abstract class Shape represents the common elements of the concrete entities circle and square. Las características comunes de todas las formas (en un sistema de coordenadas bidimensional) se abstraen en la clase de forma: la posición en la cuadrícula, un ángulo de rotación y las propiedades del área y del perímetro.The common features of all shapes (in a two-dimensional coordinate system) are abstracted out into the Shape class: the position on the grid, an angle of rotation, and the area and perimeter properties. Se pueden invalidar, excepto en el caso de la posición, el comportamiento de las formas individuales que no pueden cambiar.These can be overridden, except for position, the behavior of which individual shapes cannot change.

Se puede invalidar el método de rotación, como en la clase Circle, que es la rotación invariable debido a su simetría.The rotation method can be overridden, as in the Circle class, which is rotation invariant because of its symmetry. Por lo tanto, en la clase Circle, el método de rotación se reemplaza por un método que no hace nada.So in the Circle class, the rotation method is replaced by a method that does nothing.

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

Salida: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

Vea tambiénSee also