Clases de PowerShell: introducción
PowerShell es un lenguaje orientado a objetos. Cuando ejecuta comandos, vea el resultado en su pantalla, esos son objetos. Los objetos no surgen simplemente de la nada; los desarrolladores los crean o, más específicamente, los crean instancias con clases. Las clases de PowerShell representan definiciones o esquemas de esos objetos.
Aunque es posible que esté familiarizado con la creación de objetos con comandos como New-Object y el uso del acelerador de tipo pscustomobject, estos no son objetos "nuevos". Los tipos de objetos que estos métodos producen son de un tipo específico. Las clases de PowerShell definen el tipo.
En este tutorial, aprenderá cómo comenzar con las clases de PowerShell. Crearás tu primera clase con constructores, aprenderás a crear objetos a partir de tu clase y decorarás tu clase con propiedades y métodos.
Para obtener información general sobre términos como objetos, propiedades y métodos, consulte la publicación del blog Regreso a lo básico: comprensión de los objetos de PowerShell.
Requisitos previos
Creando su primera clase y objeto
Antes de que pueda aprender los entresijos de una clase de PowerShell, primero debe explicar cómo crear una clase simple. Aprenderá sobre los temas más avanzados más adelante.
Crear su primera clase se sentirá un poco como crear una función. La sintaxis básica es la misma. Una clase se crea a partir de una definición como una función. Sin embargo, a diferencia de las funciones, la primera línea no comienza con function seguida del nombre de la función, sino que comienza con class seguida del nombre de su tipo de objeto.
A continuación verás el esqueleto básico de una clase llamada estudiante.
class student {
}Las clases tienen propiedades que parecen parámetros que son atributos que describen esa clase. El siguiente ejemplo muestra una clase llamada estudiante con dos propiedades; Nombre y Apellido.
Cuando define una propiedad, siempre debe definir un tipo que establezca un "esquema" específico para los valores de propiedad que pueden contener. En el siguiente ejemplo, ambas propiedades se definen como cadenas.
Siempre debes definir los tipos de propiedad. Verás por qué más tarde.
class student {
[string]$FirstName
[string]$LastName
}Después de definir una clase, cree un objeto a partir de ella o cree una instancia de un objeto. Hay varias formas de crear instancias de objetos a partir de clases; una forma común es usar aceleradores de tipos como [student] que representan la clase, seguido de un método predeterminado que viene con cada clase llamado new().
Usar el atajo del acelerador de tipos es lo mismo que crear un objeto usando el comando New-Object.
New-Object -TypeName studentUna vez que haya creado un objeto de esa clase, asigne valores a las propiedades. El siguiente ejemplo asigna valores de Tyler y Muir para las propiedades FirstName y LastName.
class student {
[string]$FirstName
[string]$LastName
}
$student1 = [student]::new()
$student1.FirstName = 'Tyler'
$student1.LastName = 'Muir'
$student1Una vez que haya creado el objeto y haya asignado valores a las propiedades, inspeccione el objeto llamando a la variable a la que asignó el objeto, como se muestra a continuación.
Ahora que ha creado un objeto a partir de una clase, canalice ese objeto como cualquier otro objeto en PowerShell al cmdlet Get-Member para inspeccionarlo. Puede ver a continuación que el objeto contenido dentro de la variable $student1 es de tipo student.
El nombre de la clase siempre se correlacionará con el tipo de objeto.
Observe que Get-Member devuelve cuatro métodos y dos propiedades. Las propiedades probablemente le resulten familiares, pero los métodos seguro que no. PowerShell agrega ciertos métodos de forma predeterminada, pero usted puede agregar sus propios métodos o incluso modificar los métodos predeterminados.
Creación de métodos
En el ejemplo anterior, vio algunos métodos predeterminados en el objeto, pero es probable que desee crear los suyos propios. Para hacer eso, debe definir uno o más métodos dentro de la definición de clase.
La definición de un método se ve a continuación con un tipo de salida que define qué tipo de objeto se devuelve desde este método, el nombre del método y el código que se ejecutará dentro de un scriptblock.
[<output type>]<name>() {
<code that runs when the method is executed>
}Observe los paréntesis () después del nombre. Aquí es donde puede definir los parámetros del método (que se tratan más adelante). Los parámetros del método le permiten cambiar la funcionalidad de un método tal como puede hacerlo con los parámetros de la función.
Si ha escrito y ejecutado funciones de PowerShell antes, los bloques de secuencias de comandos de métodos le resultarán familiares, pero hay un par de reglas especiales para los métodos que debe conocer.
return es obligatorio
Las funciones de PowerShell devolverán objetos simplemente colocando el objeto en cualquier lugar de la función, como en el siguiente ejemplo.
function foo {
$object = Get-Service
$object ## Just sending the object to the pipeline
}Sin embargo, a diferencia de las funciones, si un método devuelve un objeto, debe utilizar la construcción return como se muestra a continuación.
[string]GetName() {
return 'foo'
}Usando la variable $this
Otra diferencia que tienen los métodos con las funciones es la variable $this. La variable $this, tal como se define dentro de un método, hace referencia a las propiedades del objeto actual u otros métodos.
A continuación se muestra un ejemplo de un método llamado GetName() agregado a la clase student que concatena el valor de FirstName y Apellido propiedades y las devuelve.
class student {
[string]$FirstName
[string]$LastName
[string]GetName() {
return "$($this.FirstName) $($this.LastName)"
}
}Ahora puede llamar al método GetName() usando la notación de puntos como se muestra a continuación. Si previamente asignó valores a FirstName y LastName, GetName() los devolverá.
Agregar parámetros a métodos
En el ejemplo anterior, cuando ejecutaste la línea $student1.GetName(), estabas llamando al método GetName() tal cual. Dentro de los paréntesis, puede definir parámetros como funciones.
El método GetName() acaba de devolver los valores establecidos para las propiedades FirstName y LastName. Pero, ¿qué pasa si prefieres tener un método para establecer propiedades que GetName() pueda luego obtener? En ese caso, necesita definir los parámetros del método.
Defina los parámetros del método incluyendo uno o más parámetros separados por una coma en los paréntesis de los parámetros del método, como se muestra a continuación.
Tenga en cuenta el tipo de salida
[void]. Siempre que un método no genera nada, no necesita una construcciónreturny debe definir el tipo de salida como[void]para indicarle a PowerShell que el método no devuelve nada. .
[void]SetName([string]$Name) {
}Por ejemplo, quizás el método SetName() acepte un nombre completo (nombre y apellido). Si es así, en el bloque de secuencia de comandos, puede dividir esta cadena y asignar el nombre y apellido de esa manera.
Al insertar el método SetName() en la clase student, a continuación se muestra cómo se ve ahora.
class student {
[string]$FirstName
[string]$LastName
[string]GetName() {
return "$($this.FirstName) $($this.LastName)"
}
[void]SetName([string]$Name) {
$this.FirstName = ($Name -split ' ')[0]
$this.LastName = ($Name -split ' ')[1]
}
}Ahora puede pasar un nombre completo como parámetro al método SetName(), que establece las propiedades FirstName y LastName del objeto actual.
Métodos de sobrecarga
Quizás desee definir diferentes conjuntos de parámetros para un método. De manera similar a cómo funcionan los conjuntos de parámetros en funciones y cmdlets, puede definir diferentes “contextos” de parámetros o firmas de métodos.
Tal vez desee configurar los parámetros FirstName y LastName pasando un nombre completo al método SetName() o pasando el nombre y el apellido. nombre por separado. No tienes que elegir; puedes definirlos a ambos con firmas de métodos.
Cuando defines más de una firma de método en una clase, eso se llama sobrecarga.
Reutilizando el ejemplo de la sección anterior, puede crear una sobrecarga para el método SetName() para aceptar dos cadenas en lugar de una. Cuando pasa dos cadenas en lugar de una, el método SetName() asume que la primera cadena es FirstName y la segunda cadena es LastName. . Con esa sobrecarga, la clase quedaría como la siguiente.
class student {
[string]$FirstName
[string]$LastName
[string]GetName() {
return "$($this.FirstName) $($this.LastName)"
}
[void]SetName([string]$Name) {
$this.FirstName = ($Name -split ' ')[0]
$this.LastName = ($Name -split ' ')[1]
}
[void]SetName([string]$FirstName,[string]$LastName) {
$this.FirstName = $FirstName
$this.LastName = $LastName
}
}Constructores de clases
Siempre que crea una instancia de un objeto con el método new() o de otra manera, puede indicarle a PowerShell que ejecute algún código definido por el usuario llamado constructor. Los constructores son como métodos, pero se ejecutan automáticamente cuando PowerShell crea una instancia de un objeto.
Cada clase tiene un constructor predeterminado. Este constructor predeterminado no hace mucho; solo se encarga de crear una instancia del objeto. Puede ver el constructor predeterminado viendo la salida del método New. Puede ver a continuación que esta línea devuelve un único método new().
[student]::NewSobrecarga de constructores
Quizás desee establecer un valor para las propiedades FirstName y LastName tan pronto como cree el objeto, no con la típica notación de puntos. En ese caso, puede crear un constructor con un parámetro que luego llame a SetName().
A continuación se muestra un ejemplo de un constructor para la clase student. Observe que el constructor no tiene un nombre específico ni va precedido de un tipo de salida. Los constructores siempre usan el mismo nombre que la clase.
Llamar a un método existente en el constructor nos permite reutilizar el método que ya escribimos para manejar la configuración de las variables.
student([string]$Name) {
$this.SetName($Name)
}Y debajo verás ese constructor agregado a la clase student.
class student {
[string]$FirstName
[string]$LastName
student([string]$Name) {
$this.SetName($Name)
}
[string]GetName() {
return "$($this.FirstName) $($this.LastName)"
}
[void]SetName([string]$Name) {
$this.FirstName = ($Name -split ' ')[0]
$this.LastName = ($Name -split ' ')[1]
}
[void]SetName([string]$FirstName,[string]$LastName) {
$this.FirstName = $FirstName
$this.LastName = $LastName
}
}Cuando crea una instancia de un nuevo objeto student y pasa un parámetro de cadena, las propiedades del objeto tendrán inmediatamente los valores esperados.
Ahora puedes volver a ver el constructor sobrecargado con [student]::New. Observe ahora que el nuevo constructor sobrecargado se define con un parámetro Name.
Definición de un constructor predeterminado y sobrecargado
Ahora que tiene un constructor sobrecargado en su clase student, PowerShell sobrescribe el constructor predeterminado. Pero puede recuperarlo creando uno manualmente sin parámetros.
student() {}Puedes ver cómo se ve en la clase student a continuación.
class student {
[string]$FirstName
[string]$LastName
student([string]$Name) {
$this.SetName($Name)
}
student() {}
[void]SetName([string]$Name) {
$this.FirstName = ($Name -split ' ')[0]
$this.LastName = ($Name -split ' ')[1]
}
}Ahora revisa los constructores nuevamente. Ahora verás aparecer ambos constructores.
[student]::NewHerencia de clases
Como todos los demás lenguajes orientados a objetos, puede crear clases de PowerShell de forma jerárquica con varias clases. Cada clase puede tener clases "principales" y "secundarias" que comienzan con propósitos menos específicos y más genéricos y aumentan la especificidad.
Por ejemplo, nuestra clase estudiante representa a un estudiante universitario (niño/específico). Ese estudiante universitario es una persona (padre/genérico). Estos dos conceptos están relacionados y forman una jerarquía.
Una clase secundaria puede heredar una clase principal, lo que significa que puede contener todas las propiedades y métodos (miembros) definidos a través de una clase principal. Sabemos que una clase persona puede tener propiedades como eye_color, height y weight y quizás un método llamado < código>Establecer altura().
Si un estudiante es una persona, ese estudiante todavía tiene esas propiedades y métodos. Se duplicaría el esfuerzo implementar esos mismos miembros en la clase student que ya tiene la clase person. Puede definir la herencia de clases para definir automáticamente todos los miembros de la clase person en la clase student.
Si esto no tiene sentido ahora, lo tendrá mientras avanzamos en una demostración.
Demostración de herencia de clases
Primero, haga una copia de la clase estudiante que creó anteriormente, elimine los constructores y cámbiele el nombre a clase persona. A su clase person le debería gustar la siguiente clase.
Un estudiante, por supuesto, tiene un nombre y un apellido, pero la clase se puede describir con mayor precisión etiquetándola como una persona. Al crear una clase más "genérica" como esta, puede crear clases "secundarias" más específicas a partir de ella.
class person {
[string]$FirstName
[string]$LastName
[string]GetName() {
return "$($this.FirstName) $($this.LastName)"
}
[void]SetName([string]$Name) {
$this.FirstName = ($Name -split ' ')[0]
$this.LastName = ($Name -split ' ')[1]
}
[void]SetName([string]$FirstName,[string]$LastName) {
$this.FirstName = $FirstName
$this.LastName = $LastName
}
}Ahora, crea un par de clases que representen a una persona pero que tengan un rol más específico. Por ejemplo, en el fragmento de código siguiente, ahora tiene una clase profesor y estudiante.
class teacher {
[int]$EmployeeId
}
class student {
[int]$StudentId
}Tal como están, las clases maestro y estudiante son mutuamente excluyentes de la clase persona. No tienen ninguna relación pero no pueden heredar ningún miembro de la clase person. Cambiemos eso.
Ahora defina esa jerarquía definiendo las clases profesor y student como clases “secundarias” de la clase person con herencia. Puede definir la herencia agregando dos puntos (:) después del nombre de la clase seguido del nombre de la clase principal como se muestra a continuación.
class teacher : person {
[int]$EmployeeId
}
class student : person {
[int]$StudentId
}Todo el script de tu clase ahora debería verse así:
class person {
[string]$FirstName
[string]$LastName
[string]GetName() {
return "$($this.FirstName) $($this.LastName)"
}
[void]SetName([string]$Name) {
$this.FirstName = ($Name -split ' ')[0]
$this.LastName = ($Name -split ' ')[1]
}
[void]SetName([string]$FirstName,[string]$LastName) {
$this.FirstName = $FirstName
$this.LastName = $LastName
}
}
class teacher : person {
[int]$EmployeeId
}
class student : person {
[int]$StudentId
}
En este punto, cuando crea una instancia de un objeto de la clase teacher o student, ambas clases tendrán los mismos miembros que la clase person.
Heredar con constructores
Como vio anteriormente, los métodos de clase se heredan mediante herencia de clases. Este comportamiento puede llevarte a pensar que los constructores seguirían la misma lógica, pero estarías equivocado. Los constructores no se heredan y los constructores de todas las clases secundarias deben definirse en cada clase secundaria por separado.
Por ejemplo, tal vez acaba de definir un constructor sobrecargado para la clase person pero no definió un constructor para la clase teacher, como se muestra a continuación.
class person {
[string]hidden $FirstName
[string]$LastName
[string]GetName() {
return "$($this.FirstName) $($this.LastName)"
}
[void]SetName([string]$Name) {
$this.FirstName = ($Name -split ' ')[0]
$this.LastName = ($Name -split ' ')[1]
}
[void]SetName([string]$FirstName,[string]$LastName) {
$this.FirstName = $FirstName
$this.LastName = $LastName
}
person([string]$Name) {
$this.SetName($Name)
}
}Luego define una clase secundaria, teacher, por ejemplo, e intenta crear un objeto sin parámetros, como se muestra a continuación. Observe que PowerShell devuelve un error porque no se definió un constructor sin parámetros dentro de la clase teacher.
No es necesario un constructor en una clase secundaria si solo lo usas como plantilla. Alternativamente, si desea utilizar la clase principal como su propia clase independiente y como clase principal, puede incluir constructores. Pero debes asegurarte de que la clase principal tenga un constructor que coincida con los de las clases secundarias.
Atributos de los miembros de la clase
Al igual que los parámetros de comando de PowerShell, las clases pueden tener atributos de miembro. Estos atributos modifican el comportamiento de cada miembro.
Miembros ocultos
Si está utilizando un miembro de la clase solo para fines internos y no desea que el usuario lea o escriba en él, configure un miembro como oculto. Por ejemplo, tal vez tenga un método que solo utilicen otros métodos. No es necesario exponer ese método al usuario.
Para definir un miembro oculto, utilice el atributo hidden como se muestra a continuación.
class teacher {
[int]hidden $EmployeeId
}Ahora, cuando usas Get-Member para inspeccionar todos los miembros del objeto, esa propiedad no aparece.
Establecer un miembro de la clase como oculto no restringe el acceso al valor; sólo lo oculta a la vista. No debes ocultar propiedades para almacenar datos confidenciales.
Miembros estáticos
Recuerde antes; Este tutorial utilizó el término "crear una instancia" para describir la creación de un objeto a partir de una clase. Cuando crea una instancia de un objeto, ese objeto adquiere todas las propiedades y métodos que define la clase. Pero ese no es siempre el caso.
A veces, no es necesario la sobrecarga de crear una instancia de un objeto completo. En su lugar, debe hacer referencia rápidamente a un único miembro de la clase. En ese caso, puede configurar un miembro de la clase como estático.
Al igual que con el atributo hidden, defina un miembro de clase como estático usando la palabra clave static como se muestra a continuación.
class student {
[int]static $MaxClassCount = 7
}A diferencia de los miembros de clase típicos, PowerShell no crea propiedades ni métodos a partir de miembros de clase estáticos. Cuando defines un miembro de una clase como estático, como miembros ocultos, no aparece cuando usas Get-Member.
Por ejemplo, tal vez desee asociar nombres de clases universitarias con la clase estudiante y definir el número máximo de clases universitarias en las que un estudiante puede participar. Para hacerlo, cree una clase Clases. miembro de matriz y un miembro MaxClassCount.
Dado que el usuario rara vez necesita cambiar el miembro MaxClassCount, decide definirlo como estático.
Finalmente, crea un método AddClass() para agregar una clase al horario del estudiante, pero solo si es menor que ese MaxClassCount.
class student {
[string[]]$Classes = @()
[int]static $MaxClassCount = 7
[void]AddClass ([string]$Name) {
if ($this.Classes.Count -lt [student]::MaxClassCount) {
$this.Classes += $Name
}
}
}Ahora, cuando intente crear un nuevo objeto student y le asigne demasiadas clases universitarias, PowerShell solo asignará el número máximo, que sería siete.
$student1 = [student]::new()
'PE','English','Math','History','Computer Science','French','Wood Working','Cooking' | ForEach-Object {
$student1.AddClass($_)
}
$student1.ClassesPuedes cambiar los valores de los miembros estáticos en cualquier momento. Si, por ejemplo, quisiera que el miembro
MaxClassCountfuera 5 en lugar de 7, cambiaría el valor usando[student]::MaxClassCount=5. Cambiar el valor no eliminaría retroactivamente las clases que superan el límite en este ejemplo.
Conclusión
Las clases de PowerShell desdibujan la línea entre un lenguaje de scripting y un lenguaje de programación. Las clases son una excelente manera de definir relaciones entre objetos, agregar formas de interactuar y formatear objetos que normalmente solo serían posibles escribiendo funciones especializadas.













