Construtores (F#)
Este tópico descreve como definir e usar os construtores para criar e inicializar objetos de classe e estrutura.
Construção de objetos de classes
Objetos de tipos de classe tem construtores. Existem dois tipos de construtores. Um é o construtor primário, cujos parâmetros aparecem entre parênteses, logo após o nome do tipo. Você especifica, opcionais construtores adicionais usando o new palavra-chave. Esses construtores de adicionais devem chamar o construtor primário.
O construtor primário contém let e do ligações que aparecem no início da definição de classe. A let vinculação declara campos privados e métodos da classe; um do ligação executa o código. Para obter mais informações sobre let ligações em construtores de classe, consulte Associações let em classes (F#). Para obter mais informações sobre do ligações em construtores, consulte Associações do em classes (F#).
Independentemente do construtor que você deseja chamar um construtor primário ou um construtor adicional, você pode criar objetos usando um new expressão, com ou sem o opcional new palavra-chave. Inicializar os objetos junto com os argumentos do construtor, seja pelo listando os argumentos na ordem e separados por vírgulas e entre parênteses ou usando os argumentos nomeados e valores entre parênteses. Você também pode definir propriedades em um objeto durante a construção do objeto usando os nomes de propriedade e atribuir valores assim como você usa chamado argumentos do construtor.
O código a seguir ilustra uma classe que tem um construtor e várias maneiras de criar objetos.
// This class has a primary constructor that takes three arguments
// and an additional constructor that calls the primary constructor.
type MyClass(x0, y0, z0) =
let mutable x = x0
let mutable y = y0
let mutable z = z0
do
printfn "Initialized object that has coordinates (%d, %d, %d)" x y z
member this.X with get() = x and set(value) = x <- value
member this.Y with get() = y and set(value) = y <- value
member this.Z with get() = z and set(value) = z <- value
new() = MyClass(0, 0, 0)
// Create by using the new keyword.
let myObject1 = new MyClass(1, 2, 3)
// Create without using the new keyword.
let myObject2 = MyClass(4, 5, 6)
// Create by using named arguments.
let myObject3 = MyClass(x0 = 7, y0 = 8, z0 = 9)
// Create by using the additional constructor.
let myObject4 = MyClass()
A saída é da seguinte maneira.
Initialized object that has coordinates (1, 2, 3)
Initialized object that has coordinates (4, 5, 6)
Initialized object that has coordinates (7, 8, 9)
Initialized object that has coordinates (0, 0, 0)
Construção de estruturas
Estruturas de seguem todas as regras de classes. Portanto, você pode ter um construtor primário e você pode fornecer construtores adicionais usando new. No entanto, há uma diferença importante entre estruturas e classes: estruturas podem ter um construtor padrão (ou seja, um sem argumentos), mesmo se nenhum construtor primário é definido. O construtor padrão inicializa todos os campos para o valor padrão para esse tipo, geralmente zero ou seu equivalente. Os construtores que você define para estruturas devem ter pelo menos um argumento para que eles não entrem em conflito com o construtor padrão.
Além disso, as estruturas geralmente têm campos que são criados usando o val palavra-chave; classes também podem ter esses campos. Estruturas e classes que possuem campos definidos usando o val palavra-chave pode também ser inicializado em construtores adicionais usando expressões de registros, conforme mostrado no código a seguir.
type MyStruct =
struct
val X : int
val Y : int
val Z : int
new(x, y, z) = { X = x; Y = y; Z = z }
end
let myStructure1 = new MyStruct(1, 2, 3)
Para obter mais informações, consulte Campos explícitos: a palavra-chave val (F#).
Efeitos colaterais em execução em construtores
Um construtor primário em uma classe pode executar código em um do vinculação. No entanto, se você tiver que executar o código em um construtor adicional, sem um do ligação? Para fazer isso, use o then palavra-chave.
// Executing side effects in the primary constructor and
// additional constructors.
type Person(nameIn : string, idIn : int) =
let mutable name = nameIn
let mutable id = idIn
do printfn "Created a person object."
member this.Name with get() = name and set(v) = name <- v
member this.ID with get() = id and set(v) = id <- v
new() =
Person("Invalid Name", -1)
then
printfn "Created an invalid person object."
let person1 = new Person("Humberto Acevedo", 123458734)
let person2 = new Person()
Os efeitos colaterais do construtor primário ainda executar. Portanto, a saída é da seguinte maneira.
Created a person object.
Created a person object.
Created an invalid person object.
Auto-identificadores em construtores
Em outros membros, você deve fornecer um nome para o objeto atual na definição de cada membro. Você também pode colocar o identificador de auto-na primeira linha da definição da classe usando o as imediatamente após os parâmetros do construtor de palavra-chave. O exemplo a seguir ilustra essa sintaxe.
type MyClass1(x) as this =
// This use of the self identifier produces a warning - avoid.
let x1 = this.X
// This use of the self identifier is acceptable.
do printfn "Initializing object with X =%d" this.X
member this.X = x
Em construtores adicionais, você também pode definir um identificador de auto-colocando o as cláusula logo após os parâmetros do construtor. O exemplo a seguir ilustra essa sintaxe.
type MyClass2(x : int) =
member this.X = x
new() as this = MyClass2(0) then printfn "Initializing with X = %d" this.X
Podem ocorrer problemas quando você tenta usar um objeto antes que ele esteja totalmente definido. Portanto, usos do identificador do auto-podem fazer com que o compilador emitir um aviso e inserir verificações adicionais para garantir que os membros de um objeto não são acessados antes que o objeto seja inicializado. Você só deve usar o identificador de auto-na do ligações do construtor principal, ou após a then palavra-chave em construtores adicionais.
O nome do identificador do auto-não precisa ser this. Ele pode ser qualquer identificador válido.
Atribuindo valores a propriedades de inicialização
Você pode atribuir valores às propriedades de um objeto de classe no código de inicialização, acrescentando uma lista de atribuições do formulário property = value para a lista de argumentos para construtor. Isso é mostrado no exemplo de código a seguir.
type Account() =
let mutable balance = 0.0
let mutable number = 0
let mutable firstName = ""
let mutable lastName = ""
member this.AccountNumber
with get() = number
and set(value) = number <- value
member this.FirstName
with get() = firstName
and set(value) = firstName <- value
member this.LastName
with get() = lastName
and set(value) = lastName <- value
member this.Balance
with get() = balance
and set(value) = balance <- value
member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount
let account1 = new Account(AccountNumber=8782108,
FirstName="Darren", LastName="Parker",
Balance=1543.33)
A versão seguinte do código anterior ilustra a combinação de configurações de propriedade na chamada de um construtor, argumentos opcionais e argumentos comuns.
type Account(accountNumber : int, ?first: string, ?last: string, ?bal : float) =
let mutable balance = defaultArg bal 0.0
let mutable number = accountNumber
let mutable firstName = defaultArg first ""
let mutable lastName = defaultArg last ""
member this.AccountNumber
with get() = number
and set(value) = number <- value
member this.FirstName
with get() = firstName
and set(value) = firstName <- value
member this.LastName
with get() = lastName
and set(value) = lastName <- value
member this.Balance
with get() = balance
and set(value) = balance <- value
member this.Deposit(amount: float) = this.Balance <- this.Balance + amount
member this.Withdraw(amount: float) = this.Balance <- this.Balance - amount
let account1 = new Account(8782108, bal = 543.33,
FirstName="Raman", LastName="Iyer")
Construtores estáticos ou construtores de tipo
Em adição para especificar o código para a criação de objetos, estáticos let e do ligações podem ser criadas em tipos de classe que executar antes o tipo é usado primeiro para executar a inicialização no nível do tipo. Para obter mais informações, consulte Associações let em classes (F#) e Associações do em classes (F#).