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.
Um método é uma função associada a um tipo. Na programação orientada a objetos, os métodos são usados para expor e implementar a funcionalidade e o comportamento de objetos e tipos.
Sintaxe
// 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 ]
Observações
Na sintaxe anterior, você pode ver as várias formas de declarações e definições de método. Em corpos de método mais longos, uma quebra de linha segue o sinal de igual (=) e todo o corpo do método é recuado.
Os atributos podem ser aplicados a qualquer declaração de método. Eles precedem a sintaxe de uma definição de método e geralmente são listados em uma linha separada. Para obter mais informações, consulte Attributes.
Os métodos podem ser marcados inline. Para obter informações sobre inline, consulte Funções Embutidas.
Métodos não embutidos podem ser usados recursivamente dentro do tipo; não é necessário usar explicitamente a rec palavra-chave.
Métodos de instância
Os métodos de instância são declarados com a memberpalavra-chave e um auto-identificador, seguidos por um período (.) e o nome e os parâmetros do método. Como é o caso das let associações, a lista de parâmetros pode ser um padrão. Normalmente, você coloca parâmetros de método em parênteses em uma forma de tupla, que é a maneira como os métodos aparecem em F# quando são criados em outras linguagens do .NET Framework. No entanto, a forma curried (parâmetros separados por espaços) também é comum, e outros padrões também têm suporte.
O exemplo a seguir ilustra a definição e o uso de um método de instância não abstrato.
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
Em métodos de instância, não use o auto-identificador para acessar campos definidos usando let associações. Use o auto-identificador ao acessar outros membros e propriedades.
Métodos estáticos
A palavra-chave static é usada para especificar que um método pode ser chamado sem uma instância e não está associado a uma instância de objeto. Caso contrário, os métodos são métodos de instância.
O exemplo na próxima seção mostra campos declarados com a let palavra-chave, os membros da propriedade declarados com a member palavra-chave e um método estático declarado com a static palavra-chave.
O exemplo a seguir ilustra a definição e o uso de métodos estáticos. Suponha que essas definições de método estejam na SomeType classe na seção anterior.
static member SomeStaticMethod(a, b, c) =
(a + b + c)
static member SomeOtherStaticMethod(a, b, c) =
SomeType.SomeStaticMethod(a, b, c) * 100
Métodos abstratos e virtuais
A palavra-chave abstract indica que um método tem um slot de expedição virtual e pode não ter uma definição na classe. Um slot de expedição virtual é uma entrada em uma tabela de funções mantida internamente que é usada em tempo de execução para pesquisar chamadas de função virtual em um tipo orientado a objeto. O mecanismo de expedição virtual é o mecanismo que implementa o polimorfismo, um recurso importante da programação orientada a objetos. Uma classe que tem pelo menos um método abstrato sem uma definição é uma classe abstrata, o que significa que nenhuma instância pode ser criada dessa classe. Para obter mais informações sobre classes abstratas, consulte Classes Abstratas.
As declarações de método abstrato não incluem um corpo do método. Em vez disso, o nome do método é seguido por dois-pontos (:) e uma assinatura de tipo para o método. A assinatura de tipo de um método é a mesma mostrada pelo IntelliSense quando você pausa o ponteiro do mouse sobre um nome de método no Editor do Visual Studio Code, exceto sem nomes de parâmetro. As assinaturas de tipo também são exibidas pelo interpretador, fsi.exe, quando você está trabalhando interativamente. A assinatura de tipo de um método é formada pela listagem dos tipos dos parâmetros, seguidos pelo tipo de retorno, com símbolos separadores apropriados. Parâmetros curried são separados por -> e parâmetros de tupla são separados por *. O valor retornado é sempre separado dos argumentos por um -> símbolo. Parênteses podem ser usados para agrupar parâmetros complexos, como quando um tipo de função é um parâmetro ou para indicar quando uma tupla é tratada como um único parâmetro e não como dois parâmetros.
Você também pode fornecer definições padrão de métodos abstratos adicionando a definição à classe e usando a default palavra-chave, conforme mostrado no bloco de sintaxe neste tópico. Um método abstrato que tem uma definição na mesma classe é equivalente a um método virtual em outras linguagens do .NET Framework. Se existe ou não uma definição, a abstract palavra-chave cria um novo slot de expedição na tabela de funções virtuais para a classe.
Independentemente de uma classe base implementar seus métodos abstratos, as classes derivadas podem fornecer implementações de métodos abstratos. Para implementar um método abstrato em uma classe derivada, defina um método que tenha o mesmo nome e assinatura na classe derivada, exceto usar a override palavra-chave ou default fornecer o corpo do método. As palavras-chave override e default significam exatamente a mesma coisa. Use override se o novo método substituir uma implementação de classe base; use default quando você criar uma implementação na mesma classe que a declaração abstrata original. Não use a abstract palavra-chave no método que implementa o método que foi declarado abstrato na classe base.
O exemplo a seguir ilustra um método Rotate abstrato que tem uma implementação padrão, o equivalente a um método virtual do .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
O exemplo a seguir ilustra uma classe derivada que substitui um método de classe base. Nesse caso, a substituição altera o comportamento para que o método não faça nada.
type Circle(radius: float) =
inherit Ellipse(radius, radius, 0.0)
// Circles are invariant to rotation, so do nothing.
override this.Rotate(_) = ()
Métodos sobrecarregados
Métodos sobrecarregados são métodos que têm nomes idênticos em um determinado tipo, mas que têm argumentos diferentes. Em F#, os argumentos opcionais geralmente são usados em vez de métodos sobrecarregados. No entanto, métodos sobrecarregados são permitidos na linguagem, desde que os argumentos estejam na forma de tupla, não na forma curried. O exemplo a seguir demonstra:
type MyType(dataIn: int) =
let data = dataIn
member this.DoSomething(a: int) = a + data
member this.DoSomething(a: string) = sprintf "Hello world, %s!" a
let m = MyType(10)
printfn "With int: %d" (m.DoSomething(2)) // With int: 12
printfn "With string: %s" (m.DoSomething("Bill")) // With string: Hello world, Bill!
Argumentos opcionais
O F# dá suporte a argumentos opcionais para métodos. Para obter informações detalhadas sobre as diferentes formas de argumentos opcionais disponíveis em F#, consulte parâmetros opcionais.
Exemplo: propriedades e métodos
O exemplo a seguir contém um tipo que tem exemplos de campos, funções privadas, propriedades e um método estático.
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