Classes abstratas (F#)
Resumo de classes são classes que deixar alguns ou todos os membros não implementados, para que as implementações podem ser fornecidas por classes derivadas.
// 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
Comentários
Na programação orientada a objeto, uma classe abstrata é usada como uma classe base de uma hierarquia e representa a funcionalidade comum de um conjunto diversificado de tipos de objeto.Como o "Resumo" nome implica, classes abstratas geralmente não correspondem diretamente em entidades concretas do domínio do problema.No entanto, eles representam o que muitas entidades concretas diferentes têm em comum.
Classes abstratas devem ter o AbstractClass atributo.Ter implementado e não implementado membros.O uso do termo abstrata quando aplicado a uma classe é o mesmo do outro.NET idiomas; No entanto, o uso do termo abstrata quando aplicado a métodos (e propriedades) é um pouco diferente no F# do seu uso em outros.NET diferentes.Em F#, quando um método está marcado com o abstract palavra-chave, isso indica que o membro tem uma entrada, conhecida como um slot despacho virtual, na tabela interna de funções virtuais para esse tipo.Em outras palavras, o método é virtual, embora o virtual palavra-chave não é usado no idioma F#.A palavra-chave abstract é usado em métodos virtuais independentemente, por exemplo, se o método é implementado.A declaração de um slot de despacho virtual é separada da definição de um método para esse slot de despacho.Portanto, o F# equivalente de uma declaração de método virtual e a definição de outro.NET idioma é uma combinação de uma declaração de método abstrato e de uma definição separada, com um a default palavra-chave ou o override palavra-chave.Para mais informações e exemplos, consulte Métodos (F#).
Uma classe é considerada abstrata somente se houver métodos abstratos que são declarados, mas não definidos.Portanto, classes que possuem métodos abstratos não são classes abstratas necessariamente.A menos que uma classe tem undefined métodos abstratos, não use o AbstractClass atributo.
In the previous syntax, accessibility-modifier can be public, private or internal.Para obter mais informações, consulte Controle de acesso (F#).
Como ocorre com outros tipos, classes abstratas podem ter uma classe base e uma ou mais interfaces de base.Cada classe base ou interface é exibido em uma linha separada, juntamente com o inherit palavra-chave.
A definição de tipo de uma classe abstrata pode conter membros totalmente definidos, mas ele também pode conter membros abstratos.A sintaxe para membros abstratos é mostrada separadamente na sintaxe anterior.Essa sintaxe, o type signature de um membro é uma lista que contém o parâmetro tipos em ordem e os tipos de retorno, separada por -> tokens e/ou * tokens conforme apropriado para curried e parâmetros de tupled.A sintaxe para assinaturas de tipo de membro abstract é a mesma que usados nos arquivos de assinatura e que o mostrado pela IntelliSense no Editor de código de Visual Studio.
Exemplo
O código a seguir ilustra uma classe abstrata Shape, que tem duas classes derivadas de não-abstrata, Square e Circle.O exemplo mostra como usar propriedades, métodos e classes abstratas.No exemplo, a classe abstrata Shape representa os elementos comuns do círculo de entidades concreta e quadrado.Os recursos comuns de todas as formas (em um sistema de coordenadas bidimensional) são abstraídos para fora na Shape classe: a posição na grade, um ângulo de rotação e as propriedades de área e perímetro.Isso podem ser substituídos, exceto para a posição, o comportamento dos quais formas individuais não é possível alterar.
Pode do método de rotação ser substituído, como na Circle classe, que é invariável de rotação devido a sua simetria.Portanto, o Circle classe, o método de rotação é substituído por um método que não faz nada.
// 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
// overriden.
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