Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Classes abstratas são classes que deixam alguns ou todos os membros sem simplificação, para que as implementações possam ser fornecidas por classes derivadas.
Sintaxe
// 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
Observações
Na programação orientada a objetos, 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 nome "abstrato" implica, as classes abstratas geralmente não correspondem diretamente a entidades concretas no 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. Eles podem ter membros implementados e não simplificados. O uso do termo abstrato quando aplicado a uma classe é o mesmo que em outros idiomas do .NET; no entanto, o uso do termo abstrato quando aplicado a métodos (e propriedades) é um pouco diferente em F# de seu uso em outras linguagens .NET. Em F#, quando um método é marcado com a abstract palavra-chave, isso indica que um membro tem uma entrada, conhecida como slot de expedição virtual, na tabela interna de funções virtuais para esse tipo. Em outras palavras, o método é virtual, embora a virtual palavra-chave não seja usada em F#. A palavra-chave abstract é usada em métodos virtuais, independentemente de o método ser implementado. A declaração de um slot de expedição virtual é separada da definição de um método para esse slot de expedição. Portanto, o equivalente F# de uma declaração e definição de método virtual em outra linguagem .NET é uma combinação de uma declaração de método abstrato e uma definição separada, com a default palavra-chave ou a override palavra-chave. Para obter mais informações e exemplos, consulte Métodos.
Uma classe será considerada abstrata somente se houver métodos abstratos declarados, mas não definidos. Portanto, classes que têm métodos abstratos não são necessariamente classes abstratas. A menos que uma classe tenha métodos abstratos indefinidos, não use o atributo AbstractClass .
Na sintaxe anterior, o modificador de acessibilidade pode ser public, private ou internal. Para obter mais informações, consulte Controle de Acesso.
Assim como acontece com outros tipos, classes abstratas podem ter uma classe base e uma ou mais interfaces base. Cada classe base ou interface aparece em uma linha separada junto com a inherit palavra-chave.
A definição de tipo de uma classe abstrata pode conter membros totalmente definidos, mas também pode conter membros abstratos. A sintaxe para membros abstratos é mostrada separadamente na sintaxe anterior. Nessa sintaxe, a assinatura de tipo de um membro é uma lista que contém os tipos de parâmetro em ordem e os tipos de retorno, separados por -> tokens e/ou * tokens conforme apropriado para parâmetros curried e tupled. A sintaxe para assinaturas de tipo de membro abstrato é a mesma usada em arquivos de assinatura e mostrada pelo IntelliSense no Editor do Visual Studio Code.
O código a seguir ilustra uma classe abstrata Shape, que tem duas classes derivadas não abstratas, Square e Circle. O exemplo mostra como usar classes abstratas, métodos e propriedades. No exemplo, a classe abstrata Shape representa os elementos comuns do círculo e do quadrado das entidades concretas. Os recursos comuns de todas as formas (em um sistema de coordenadas bidimensional) são abstraídos na classe Shape: a posição na grade, um ângulo de rotação e as propriedades de área e perímetro. Eles podem ser substituídos, exceto pela posição, o comportamento do qual as formas individuais não podem ser alteradas.
O método de rotação pode ser substituído, como na classe Circle, que é invariável de rotação devido à sua simetria. Portanto, na classe Circle, 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
// 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
Saída:
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