ClasesClasses

Las clases son tipos que representan objetos que pueden tener propiedades, métodos y eventos.Classes are types that represent objects that can have properties, methods, and events.

SintaxisSyntax

// Class definition:
type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] =
[ class ]
[ inherit base-type-name(base-constructor-args) ]
[ let-bindings ]
[ do-bindings ]
member-list
...
[ end ]
// Mutually recursive class definitions:
type [access-modifier] type-name1 ...
and [access-modifier] type-name2 ...
...

ComentariosRemarks

Las clases representan la descripción fundamental de los tipos de objeto .NET; la clase es el concepto de tipo principal que admite la programación orientada F#a objetos en.Classes represent the fundamental description of .NET object types; the class is the primary type concept that supports object-oriented programming in F#.

En la sintaxis anterior, type-name es cualquier identificador válido.In the preceding syntax, the type-name is any valid identifier. El type-params describe los parámetros de tipo genérico opcionales.The type-params describes optional generic type parameters. Consta de los nombres de parámetro de tipo y las restricciones entre corchetes angulares< ( >y).It consists of type parameter names and constraints enclosed in angle brackets (< and >). Para obtener más información, vea Genéricos y Restricciones.For more information, see Generics and Constraints. Describe parameter-list los parámetros de constructor.The parameter-list describes constructor parameters. El primer modificador de acceso pertenece al tipo; el segundo pertenece al constructor principal.The first access modifier pertains to the type; the second pertains to the primary constructor. En ambos casos, el valor predeterminado publices.In both cases, the default is public.

La clase base de una clase se especifica mediante la inherit palabra clave.You specify the base class for a class by using the inherit keyword. Debe proporcionar argumentos, entre paréntesis, para el constructor de clase base.You must supply arguments, in parentheses, for the base class constructor.

Declare los campos o valores de función que son locales de la clase let mediante enlaces y debe seguir las reglas generales para let los enlaces.You declare fields or function values that are local to the class by using let bindings, and you must follow the general rules for let bindings. En do-bindings la sección se incluye el código que se va a ejecutar durante la construcción del objeto.The do-bindings section includes code to be executed upon object construction.

member-list Está formado por constructores adicionales, declaraciones de instancias y métodos estáticos, declaraciones de interfaz, enlaces abstractos y declaraciones de propiedades y eventos.The member-list consists of additional constructors, instance and static method declarations, interface declarations, abstract bindings, and property and event declarations. Se describen en miembros.These are described in Members.

El identifier que se usa con la palabra as clave opcional proporciona un nombre a la variable de instancia, o Self Identifier, que se puede usar en la definición de tipo para hacer referencia a la instancia del tipo.The identifier that is used with the optional as keyword gives a name to the instance variable, or self identifier, which can be used in the type definition to refer to the instance of the type. Para obtener más información, vea la sección identificadores propios más adelante en este tema.For more information, see the section Self Identifiers later in this topic.

Las palabras class clave end y que marcan el inicio y el final de la definición son opcionales.The keywords class and end that mark the start and end of the definition are optional.

Los tipos mutuamente recursivos, que son tipos que hacen referencia entre sí, se unen junto and con la palabra clave, al igual que las funciones recursivas.Mutually recursive types, which are types that reference each other, are joined together with the and keyword just as mutually recursive functions are. Para obtener un ejemplo, vea la sección tipos mutuamente recursivos.For an example, see the section Mutually Recursive Types.

ConstructoresConstructors

El constructor es código que crea una instancia del tipo de clase.The constructor is code that creates an instance of the class type. Los constructores de las clases funcionan de F# manera ligeramente diferente que en otros lenguajes .net.Constructors for classes work somewhat differently in F# than they do in other .NET languages. En una F# clase, siempre hay un constructor principal cuyos argumentos se describen en el parameter-list que sigue al nombre de tipo y cuyo cuerpo está compuesto de los let enlaces (y let rec) al principio de la declaración de clase y el do enlaces siguientes.In an F# class, there is always a primary constructor whose arguments are described in the parameter-list that follows the type name, and whose body consists of the let (and let rec) bindings at the start of the class declaration and the do bindings that follow. Los argumentos del constructor principal están en el ámbito de la declaración de clase.The arguments of the primary constructor are in scope throughout the class declaration.

Puede Agregar constructores adicionales mediante la new palabra clave para agregar un miembro, como se indica a continuación:You can add additional constructors by using the new keyword to add a member, as follows:

new(argument-list) = constructor-bodynew(argument-list) = constructor-body

El cuerpo del nuevo constructor debe invocar el constructor principal que se especifica en la parte superior de la declaración de clase.The body of the new constructor must invoke the primary constructor that is specified at the top of the class declaration.

En el ejemplo siguiente se muestra este concepto.The following example illustrates this concept. En el código siguiente, MyClass tiene dos constructores, un constructor principal que toma dos argumentos y otro que no toma ningún argumento.In the following code, MyClass has two constructors, a primary constructor that takes two arguments and another constructor that takes no arguments.

type MyClass1(x: int, y: int) =
   do printfn "%d %d" x y
   new() = MyClass1(0, 0)

permitir y realizar enlaceslet and do Bindings

Los let enlaces do y de una definición de clase forman el cuerpo del constructor de clase principal y, por lo tanto, se ejecutan cada vez que se crea una instancia de clase.The let and do bindings in a class definition form the body of the primary class constructor, and therefore they run whenever a class instance is created. Si un let enlace es una función, se compila en un miembro.If a let binding is a function, then it is compiled into a member. Si el let enlace es un valor que no se usa en ninguna función o miembro, se compila en una variable local para el constructor.If the let binding is a value that is not used in any function or member, then it is compiled into a variable that is local to the constructor. De lo contrario, se compila en un campo de la clase.Otherwise, it is compiled into a field of the class. Las do expresiones siguientes se compilan en el constructor principal y ejecutan el código de inicialización para cada instancia.The do expressions that follow are compiled into the primary constructor and execute initialization code for every instance. Dado que los constructores adicionales siempre llaman al constructor principal, let los enlaces y do enlaces siempre se ejecutan independientemente del constructor al que se llame.Because any additional constructors always call the primary constructor, the let bindings and do bindings always execute regardless of which constructor is called.

Se puede tener acceso a let los campos que se crean mediante enlaces a través de los métodos y propiedades de la clase; sin embargo, no se puede tener acceso a ellos desde métodos estáticos, incluso si los métodos estáticos toman una variable de instancia como parámetro.Fields that are created by let bindings can be accessed throughout the methods and properties of the class; however, they cannot be accessed from static methods, even if the static methods take an instance variable as a parameter. No se puede tener acceso a ellos mediante el identificador propio, si existe alguno.They cannot be accessed by using the self identifier, if one exists.

Identificadores propiosSelf Identifiers

Un identificador propio es un nombre que representa la instancia actual.A self identifier is a name that represents the current instance. Los identificadores propios se asemejan a this la palabra Me clave en C# o C++ o en Visual Basic.Self identifiers resemble the this keyword in C# or C++ or Me in Visual Basic. Puede definir un identificador propio de dos maneras diferentes, en función de si desea que el identificador propio esté en el ámbito de la definición de clase completa o solo para un método individual.You can define a self identifier in two different ways, depending on whether you want the self identifier to be in scope for the whole class definition or just for an individual method.

Para definir un identificador propio para toda la clase, utilice la as palabra clave después del paréntesis de cierre de la lista de parámetros del constructor y especifique el nombre del identificador.To define a self identifier for the whole class, use the as keyword after the closing parentheses of the constructor parameter list, and specify the identifier name.

Para definir un identificador propio solo para un método, proporcione el identificador propio en la declaración de miembro, justo antes del nombre del método y un punto (.) como separador.To define a self identifier for just one method, provide the self identifier in the member declaration, just before the method name and a period (.) as a separator.

En el ejemplo de código siguiente se muestran las dos maneras de crear un identificador propio.The following code example illustrates the two ways to create a self identifier. En la primera línea, la as palabra clave se usa para definir el identificador propio.In the first line, the as keyword is used to define the self identifier. En la quinta línea, el identificador this se usa para definir un identificador propio cuyo ámbito está restringido al método. PrintMessageIn the fifth line, the identifier this is used to define a self identifier whose scope is restricted to the method PrintMessage.

type MyClass2(dataIn) as self =
    let data = dataIn
    do
        self.PrintMessage()
    member this.PrintMessage() =
        printf "Creating MyClass2 with Data %d" data

A diferencia de otros lenguajes de .NET, puede asignar un nombre al propio identificador si lo desea; no está restringido a nombres como self, Meo this.Unlike in other .NET languages, you can name the self identifier however you want; you are not restricted to names such as self, Me, or this.

El identificador propio que se declara con la as palabra clave no se inicializa hasta que se ejecutan los let enlaces.The self identifier that is declared with the as keyword is not initialized until after the let bindings are executed. Por lo tanto, no se puede usar let en los enlaces.Therefore, it cannot be used in the let bindings. Puede usar el identificador propio en la do sección de enlaces.You can use the self identifier in the do bindings section.

Parámetros de tipos genéricosGeneric Type Parameters

Los parámetros de tipo genérico se especifican entre corchetes angulares (< y >), en forma de comillas simples seguidos de un identificador.Generic type parameters are specified in angle brackets (< and >), in the form of a single quotation mark followed by an identifier. Varios parámetros de tipo genérico se separan mediante comas.Multiple generic type parameters are separated by commas. El parámetro de tipo genérico está en el ámbito de la declaración.The generic type parameter is in scope throughout the declaration. En el ejemplo de código siguiente se muestra cómo especificar parámetros de tipo genérico.The following code example shows how to specify generic type parameters.

type MyGenericClass<'a> (x: 'a) =
   do printfn "%A" x

Los argumentos de tipo se deducen cuando se usa el tipo.Type arguments are inferred when the type is used. En el código siguiente, el tipo deducido es una secuencia de tuplas.In the following code, the inferred type is a sequence of tuples.

let g1 = MyGenericClass( seq { for i in 1 .. 10 -> (i, i*i) } )

Especificar herenciaSpecifying Inheritance

La inherit cláusula identifica la clase base directa, si hay alguna.The inherit clause identifies the direct base class, if there is one. En F#, solo se permite una clase base directa.In F#, only one direct base class is allowed. Las interfaces que implementa una clase no se consideran clases base.Interfaces that a class implements are not considered base classes. Las interfaces se describen en el tema interfaces .Interfaces are discussed in the Interfaces topic.

Puede tener acceso a los métodos y propiedades de la clase base desde la clase derivada mediante el uso de base la palabra clave Language como identificador, seguido de un punto (.) y el nombre del miembro.You can access the methods and properties of the base class from the derived class by using the language keyword base as an identifier, followed by a period (.) and the name of the member.

Para obtener más información, vea Herencia.For more information, see Inheritance.

Sección de miembrosMembers Section

Puede definir métodos estáticos o de instancia, propiedades, implementaciones de interfaz, miembros abstractos, declaraciones de eventos y constructores adicionales en esta sección.You can define static or instance methods, properties, interface implementations, abstract members, event declarations, and additional constructors in this section. Los enlaces Let y do no pueden aparecer en esta sección.Let and do bindings cannot appear in this section. Dado que los miembros se pueden agregar a una F# variedad de tipos además de clases, se tratan en un tema independiente, miembros.Because members can be added to a variety of F# types in addition to classes, they are discussed in a separate topic, Members.

Tipos recursivos mutuamenteMutually Recursive Types

Al definir tipos que se hacen referencia entre sí de forma circular, se concatenan las definiciones de tipos mediante la and palabra clave.When you define types that reference each other in a circular way, you string together the type definitions by using the and keyword. La and palabra clave reemplaza type la palabra clave en todas las definiciones excepto la primera, como se indica a continuación.The and keyword replaces the type keyword on all except the first definition, as follows.

open System.IO

type Folder(pathIn: string) =
  let path = pathIn
  let filenameArray : string array = Directory.GetFiles(path)
  member this.FileArray = Array.map (fun elem -> new File(elem, this)) filenameArray

and File(filename: string, containingFolder: Folder) =
   member this.Name = filename
   member this.ContainingFolder = containingFolder

let folder1 = new Folder(".")
for file in folder1.FileArray do
   printfn "%s" file.Name

La salida es una lista de todos los archivos del directorio actual.The output is a list of all the files in the current directory.

Cuándo usar clases, uniones, registros y estructurasWhen to Use Classes, Unions, Records, and Structures

Dada la variedad de tipos entre los que elegir, debe tener una buena comprensión de para qué se ha diseñado cada tipo para seleccionar el tipo adecuado para una situación determinada.Given the variety of types to choose from, you need to have a good understanding of what each type is designed for to select the appropriate type for a particular situation. Las clases están diseñadas para su uso en contextos de programación orientados a objetos.Classes are designed for use in object-oriented programming contexts. La programación orientada a objetos es el paradigma dominante utilizado en las aplicaciones escritas para el .NET Framework.Object-oriented programming is the dominant paradigm used in applications that are written for the .NET Framework. Si el F# código tiene que trabajar estrechamente con el .NET Framework u otra biblioteca orientada a objetos, y especialmente si tiene que extender desde un sistema de tipos orientado a objetos como una biblioteca de interfaz de usuario, las clases probablemente sean adecuadas.If your F# code has to work closely with the .NET Framework or another object-oriented library, and especially if you have to extend from an object-oriented type system such as a UI library, classes are probably appropriate.

Si no está interoperando estrechamente con código orientado a objetos, o si está escribiendo código que es independiente y, por tanto, está protegido contra la interacción frecuente con código orientado a objetos, considere la posibilidad de utilizar registros y uniones discriminadas.If you are not interoperating closely with object-oriented code, or if you are writing code that is self-contained and therefore protected from frequent interaction with object-oriented code, you should consider using records and discriminated unions. A menudo, se puede usar una Unión discriminada única y bien pensada, junto con el código de coincidencia de patrones adecuado, como alternativa más sencilla a una jerarquía de objetos.A single, well thought–out discriminated union, together with appropriate pattern matching code, can often be used as a simpler alternative to an object hierarchy. Para obtener más información sobre las uniones discriminadas, consulte uniones discriminadas.For more information about discriminated unions, see Discriminated Unions.

Los registros tienen la ventaja de ser más sencillos que las clases, pero los registros no son adecuados cuando las demandas de un tipo superan lo que se puede lograr con su simplicidad.Records have the advantage of being simpler than classes, but records are not appropriate when the demands of a type exceed what can be accomplished with their simplicity. Los registros son básicamente agregados de valores sencillos, sin constructores independientes que pueden realizar acciones personalizadas, sin campos ocultos y sin las implementaciones de herencia o de interfaz.Records are basically simple aggregates of values, without separate constructors that can perform custom actions, without hidden fields, and without inheritance or interface implementations. Aunque se pueden agregar miembros como propiedades y métodos a los registros para que su comportamiento sea más complejo, los campos almacenados en un registro siguen siendo un agregado simple de valores.Although members such as properties and methods can be added to records to make their behavior more complex, the fields stored in a record are still a simple aggregate of values. Para obtener más información sobre los registros, consulte registros.For more information about records, see Records.

Las estructuras también son útiles para los pequeños agregados de datos, pero difieren de las clases y los registros en que son tipos de valor de .NET.Structures are also useful for small aggregates of data, but they differ from classes and records in that they are .NET value types. Las clases y los registros son tipos de referencia de .NET.Classes and records are .NET reference types. La semántica de los tipos de valor y los tipos de referencia es diferente en que los tipos de valor se pasan por valor.The semantics of value types and reference types are different in that value types are passed by value. Esto significa que se copian bit de bit cuando se pasan como un parámetro o se devuelven desde una función.This means that they are copied bit for bit when they are passed as a parameter or returned from a function. También se almacenan en la pila o, si se usan como un campo, se insertan dentro del objeto primario en lugar de almacenarse en su propia ubicación independiente en el montón.They are also stored on the stack or, if they are used as a field, embedded inside the parent object instead of stored in their own separate location on the heap. Por lo tanto, las estructuras son adecuadas para los datos a los que se accede con frecuencia cuando la sobrecarga de tener acceso al montón es un problema.Therefore, structures are appropriate for frequently accessed data when the overhead of accessing the heap is a problem. Para obtener más información sobre las estructuras, vea estructuras.For more information about structures, see Structures.

Vea tambiénSee also