Criação de classe (atributos com hidden
são privados):
class Caneta {
hidden [string]$modelo
hidden [string]$cor
hidden [float]$ponta
hidden [bool]$tampada
[void]tampar() {
$this.tampada = $true
}
[void]destampar() {
$this.tampada = $false;
}
[void]status() {
Write-Host "Modelo:" $this.modelo
Write-Host "Cor:" $this.cor
Write-Host "Ponta:" $this.ponta
Write-Host "Tampada:" $this.tampada
}
}
Instanciação básica:
$c1 = [Caneta]::new()
$c1.status()
PS: Para pegar o nome da classe, use $this.GetType().Name
.
Caso a classe esteja em outro arquivo, chame da seguinte forma: . "$PSScriptRoot\classes.ps1"
.
PS: Pode ser necessário forçar a tipagem do objeto, por exemplo:
[Caneta]$c1 = [Caneta]::new()
$c1.status()
Classe com atributos e métodos estáticos, getters, setters, construtor e destrutor:
class Caneta {
hidden [string]$modelo
hidden [string]$cor
hidden [float]$ponta
hidden [bool]$tampada
hidden static [float]$preco = 1.50 # Estático
[void]tampar() {
$this.tampada = $true
}
[void]destampar() {
$this.tampada = $false;
}
[void]status() {
Write-Host "Modelo:" $this.modelo
Write-Host "Cor:" $this.cor
Write-Host "Ponta:" $this.ponta
Write-Host "Tampada:" $this.tampada
}
static [void]custo() { # Método estático
Write-Host "A caneta custa R$" ([Caneta]::preco)
}
Caneta([string]$m, [string]$c, [float]$p) { # Construtor
$this.modelo = $m
$this.cor = $c
$this.ponta = $p
$this.tampar()
}
[string]getModelo() {
return $this.modelo
}
[float]getPonta() {
return $this.ponta
}
[void]setModelo([string]$modelo) {
$this.modelo = $modelo
}
[void]setPonta([float]$ponta) {
$this.ponta = $ponta
}
}
PS: Caso num construtor precise inicializar um atributo como nulo, use $null
.
Uso:
[Caneta]::custo() # Chamada de método estático
$c1 = [Caneta]::new("Bic", "Azul", 0.4)
$c2 = [Caneta]::new("Pilot", "Verde", 1.0)
$c1.status()
$c2.status()
Simulação de interface com classe só com método abstratos (também simulados):
class Controlador {
[void]ligar() {
throw "Implemente o método ligar!"
}
[void]desligar() {
throw "Implemente o método desligar!"
}
[void]abrirMenu() {
throw "Implemente o método abrirMenu!"
}
[void]fecharMenu() {
throw "Implemente o método fecharMenu!"
}
[void]maisVolume() {
throw "Implemente o método maisVolume!"
}
[void]menosVolume() {
throw "Implemente o método menosVolume!"
}
[void]play() {
throw "Implemente o método play!"
}
[void]pause() {
throw "Implemente o método pause!"
}
}
Classe herdeira:
class ControleRemoto : Controlador {
hidden [int]$volume
hidden [bool]$ligado
hidden [bool]$tocando
[void]ligar() {
$this.setLigado($true)
}
[void]desligar() {
$this.setLigado($false)
}
[void]abrirMenu() {
Write-Host "Está ligado?" $this.ligado
Write-Host "Está tocando?" $this.tocando
Write-Host -NoNewline "Volume:" $this.volume
for($i = 0; $i -lt $this.volume + 1; $i++) {
Write-Host -NoNewline "|"
}
Write-Host ""
}
[void]fecharMenu() {
Write-Host "Fechando menu..."
}
[void]maisVolume() {
if($this.getLigado()) {
if($this.getVolume() -lt 100) {
$this.setVolume($this.getVolume() + 2)
}
}
else {
Write-Host "ERRO! Está Desligado, Não Posso Aumentar o Volume!"
}
}
[void]menosVolume() {
if($this.getLigado()) {
if($this.getVolume() -gt 0) {
$this.setVolume($this.getVolume() - 2)
}
}
else {
Write-Host "ERRO! Está Desligado, Não Posso Diminuir o Volume!"
}
}
[void]play() {
if($this.getLigado() -and -not $this.getTocando()) {
$this.setTocando($true)
}
}
[void]pause() {
if($this.getLigado() -and $this.getTocando()) {
$this.setTocando($false)
}
}
ControleRemoto() {
$this.volume = 50
$this.ligado = $false
$this.tocando = $false
}
[int]getVolume() {
return $this.volume
}
[bool]getLigado() {
return $this.ligado
}
[bool]getTocando() {
return $this.tocando
}
[void]setVolume([int]$volume) {
$this.volume = $volume
}
[void]setLigado([bool]$ligado) {
$this.ligado = $ligado
}
[void]setTocando([bool]$tocando) {
$this.tocando = $tocando
}
}
Instanciação:
$c = [ControleRemoto]::new()
$c.ligar()
$c.maisVolume()
$c.abrirMenu()
PS: Ao chamar métodos da classe pai na classe filha, use o método base()
no caso do construtor e os parâmetros, caso existam, fora das chaves (de forma parecida com o C#, na sintaxe NomeClasse([string]$param) : base($param) {
. Pra chamar um método específico, chame a classe e o método como ([NomeDaClasse]$this).metodo()
. Pode ser feito com qualquer método. Caso precise atribuir valor nulo à algum atributo ou variável, use $null
.
Exemplo com herança e polimorfismo:
class Mamifero {
[void]lutar() { # Abstrato simulado
throw "Implemente o método lutar!"
}
[void]respirar() {
Write-Host "Eu Respiro!"
}
[void]mamar() {
Write-Host "Eu Mamo!"
}
}
Classe herdeira:
class Gato : Mamifero {
[void]lutar() { # Override
Write-Host "Gatos Lutam Arranhando!"
}
[void]arranhar() {
Write-Host "Eu Arranho!"
}
}
Outra classe herdeira:
class Humano : Mamifero {
[void]lutar() { # Override
Write-Host "Humanos Lutam com Armas!"
}
[void]falar() {
Write-Host "Eu Falo!"
}
}
E a implementação:
$bicho = [Mamifero]::new() # Não poderia ser instanciada
$homem = [Humano]::new()
$bichano = [Gato]::new()
$homem.falar()
$homem.respirar()
$homem.lutar()
$bichano.arranhar()
$bichano.respirar()
$bichano.lutar()
PS: É possível fazer sobrecarga de métodos em Powershell, quando duas ou mais funções tem o mesmo nome mas assinaturas de parâmetros diferentes.
Vamos supor essa classe:
class Pilha {
hidden [string]$marca
hidden [int]$carga
Pilha([string]$marca) {
$this.marca = $marca
$this.carga = 100
}
[void]apresentacao() {
Write-Host ([string]::Format("A marca da pilha é {0}!", $this.marca))
Write-Host ([string]::Format("A carga da pilha é {0}%!", $this.carga))
}
[string]getMarca() {
return $this.marca
}
[int]getCarga() {
return $this.carga
}
[void]setMarca([string]$marca) {
$this.marca = $marca
}
[void]setCarga([int]$carga) {
$this.carga = $carga
}
}
Nós podemos fazer relacionamentos entre classes diferentes, veja por exemplo a classe abaixo, que tem um atributo do "tipo" da classe acima:
class Aparelho {
hidden [Pilha]$pl
Aparelho([Pilha]$pl) {
$this.pl = $pl
}
[void]ligado() {
if($this.pl.getCarga() -gt 0) { # Getter do objeto Pilha
Write-Host ([string]::Format("O aparelho está ligado e a carga da pilha é de {0}%!", $this.pl.getCarga()))
}
else {
Write-Host "A pilha do aparelho está sem carga!"
}
}
[Pilha]getPl() {
return $this.pl
}
[void]setPl([Pilha]$pl) {
$this.pl = $pl
}
}
Aí podemos chamar os objetos assim:
$ray = [Pilha]::new("Rayovac")
$ray.apresentacao()
$controle = [Aparelho]::new($ray)
$controle.ligado()
Write-Host ([string]::Format("A carga da pilha é de {0}%!", $controle.getPl().getCarga()))