Aprenda Powershell

  • Página Inicial
  • Contato!
  • Tudo sobre Powershell Parte 1!
  • Tudo sobre Powershell Parte 2!
  • Tudo sobre Powershell Parte 3!
  • Tudo sobre Powershell Parte 4!
  • Orientação a Objetos em Powershell - Parte 1

    Criando Classes e Objetos

    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()
    
    

    Métodos Estáticos, Encapsulamento e Construtor

    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()
    
    

    Abstração

    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.

    Herança e Polimorfismo

    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.

    Agregação de Objetos

    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()))