PowerShell-Klassen: Erste Schritte

PowerShell ist eine objektorientierte Sprache. Wenn Sie Befehle ausführen und die Ausgabe auf Ihrem Bildschirm sehen, handelt es sich um Objekte. Objekte entstehen nicht aus dem Nichts; Entwickler erstellen sie oder genauer gesagt, instantiieren sie mit Klassen. PowerShell-Klassen repräsentieren Definitionen oder Schemata dieser Objekte.

Auch wenn Sie möglicherweise mit der Erstellung von Objekten mit Befehlen wie New-Object und der Verwendung des pscustomobject Typbeschleunigers vertraut sind, handelt es sich dabei nicht um „neue“ Objekte. Die Arten von Objekten, die diese Methoden erzeugen, sind von einem bestimmten Typ. PowerShell-Klassen definieren den Typ.

In diesem Tutorial lernen Sie, wie Sie mit PowerShell-Klassen beginnen können. Sie erstellen Ihre erste Klasse mit Konstruktoren, lernen, wie Sie Objekte aus Ihrer Klasse erstellen und Ihre Klasse mit Eigenschaften und Methoden ausstatten.

Für Hintergrundinformationen zu Begriffen wie Objekten, Eigenschaften und Methoden lesen Sie den Blogbeitrag Zurück zu den Grundlagen: PowerShell-Objekte verstehen.

Voraussetzungen

Erstellen Ihrer ersten Klasse und Objekts

Bevor Sie die Feinheiten einer PowerShell-Klasse kennenlernen können, sollten Sie zunächst eine einfache Klasse erstellen. Die fortgeschritteneren Themen werden Sie später behandeln.

Erstellen Ihrer ersten Klasse wird sich ein wenig wie das Erstellen einer Funktion anfühlen. Die grundlegende Syntax ist die gleiche. Eine Klasse wird aus einer Definition wie einer Funktion erstellt. Anders als bei Funktionen beginnt die erste Zeile jedoch nicht mit Funktion, gefolgt vom Namen der Funktion, sondern mit Klasse, gefolgt vom Namen Ihres Objekttyps.

Unten sehen Sie das grundlegende Skelett einer Klasse namens Student.

class student {

}

Klassen haben Eigenschaften, die wie Parameter aussehen, die Attribute sind, die diese Klasse beschreiben. Das folgende Beispiel zeigt eine Klasse namens Student mit zwei Eigenschaften; Vorname und Nachname.

Wenn Sie eine Eigenschaft definieren, sollten Sie immer einen Typ definieren, der ein spezifisches „Schema“ für die Werte der Eigenschaft festlegt. Im folgenden Beispiel sind beide Eigenschaften als Zeichenfolgen definiert.

Sie sollten immer Eigenschaftstypen definieren. Sie werden später sehen, warum.

class student {
    [string]$FirstName
    [string]$LastName
}

Nachdem Sie eine Klasse definiert haben, erstellen Sie ein Objekt daraus oder instanziieren Sie ein Objekt. Es gibt mehrere Möglichkeiten, Objekte aus Klassen zu instanziieren; Eine häufige Methode besteht darin, Beschleuniger wie [Student] zu verwenden, die die Klasse repräsentieren, gefolgt von einer Standardmethode, die mit jeder Klasse geliefert wird, genannt New().

Die Verwendung des Beschleuniger-Shortcuts ist dasselbe wie das Erstellen eines Objekts unter Verwendung des Befehls New-Object.

New-Object -TypeName student

Nachdem Sie ein Objekt aus dieser Klasse erstellt haben, weisen Sie Werte den Eigenschaften zu. Das untenstehende Beispiel weist Werte von Tyler und Muir den Eigenschaften Vorname und Nachname zu.

class student {
    [string]$FirstName
    [string]$LastName
}
$student1 = [student]::new()
$student1.FirstName = 'Tyler'
$student1.LastName = 'Muir'
$student1

Nachdem Sie das Objekt erstellt und Werte den Eigenschaften zugewiesen haben, inspizieren Sie das Objekt, indem Sie die Variable aufrufen, der Sie das Objekt zugewiesen haben, wie unten gezeigt.

Creating an object from the student class.

Jetzt, da Sie ein Objekt aus einer Klasse erstellt haben, leiten Sie dieses Objekt genauso wie jedes andere Objekt in PowerShell an das Get-Member-Cmdlet weiter, um es zu inspizieren. Sie können unten sehen, dass das Objekt, das in der Variable $student1 gehalten wird, vom Typ student ist.

Der Klassenname wird immer mit dem Objekttyp korrelieren.

Beachten Sie, dass Get-Member vier Methoden und zwei Eigenschaften zurückgibt. Die Eigenschaften sehen wahrscheinlich bekannt aus, aber die Methoden sicherlich nicht. PowerShell fügt standardmäßig bestimmte Methoden hinzu, aber Sie können Ihre eigenen Methoden hinzufügen oder sogar die Standardmethoden ändern.

Showing members from custom student object.

Methoden erstellen

In obigem Beispiel haben Sie einige Standardmethoden am Objekt gesehen, aber wahrscheinlich möchten Sie Ihre eigenen erstellen. Dazu müssen Sie eine oder mehrere Methoden innerhalb der Klasendefinition definieren.

A method definition looks like below with an output type that defines what type of object is returned from this method, the name of the method, and the code to execute inside of a scriptblock.

[<output type>]<name>() {
	<code that runs when the method is executed>
}

Beachten Sie die Klammern () nach dem Namen. Hier können Sie Methodenparameter definieren (später behandelt). Methodenparameter ermöglichen es Ihnen, die Funktionalität einer Methode genauso zu ändern, wie Sie es mit Funktionsparametern tun können.

Wenn Sie zuvor PowerShell-Funktionen geschrieben und ausgeführt haben, sollten Ihnen Methoden-Skriptblöcke vertraut sein, aber es gibt ein paar spezielle Regeln für Methoden, die Sie kennen sollten.

return ist obligatorisch

PowerShell-Funktionen geben Objekte zurück, indem sie das Objekt einfach an beliebiger Stelle in der Funktion platzieren, wie im folgenden Beispiel gezeigt.

function foo {
	$object = Get-Service
	$object ## Das Objekt einfach an die Pipeline senden
}

Im Gegensatz zu Funktionen müssen Sie jedoch bei einer Methode, die ein Objekt zurückgibt, das return-Konstrukt wie unten gezeigt verwenden.

[string]GetName() {
	return 'foo'
}

Verwendung der Variable $this

Ein weiterer Unterschied zwischen Methoden und Funktionen ist die Variable $this. Die Variable $this, wie in einer Methode definiert, verweist auf die Eigenschaften oder anderen Methoden des aktuellen Objekts.

Im Folgenden finden Sie ein Beispiel für eine Methode namens GetName(), die der Klasse student hinzugefügt wurde und den Wert der Eigenschaften FirstName und LastName konkateniert und sie zurückgibt.

class student {
    [string]$FirstName
    [string]$LastName
    
    [string]GetName() {
        return "$($this.FirstName) $($this.LastName)"
    }
}

Jetzt können Sie die Methode GetName() mit der Punkt-Schreibweise aufrufen, wie unten gezeigt. Wenn Sie zuvor Werte für FirstName und LastName zugewiesen haben, gibt GetName() sie zurück.

Creating a class with a method and showing to output.

Hinzufügen von Parametern zu Methoden

In dem obigen Beispiel haben Sie beim Ausführen der Zeile $student1.GetName() die Methode GetName() unverändert aufgerufen. Innerhalb der Klammern können Sie Parameter definieren, ähnlich wie bei Funktionen.

Die Methode GetName() hat einfach die Werte zurückgegeben, die für die Eigenschaften FirstName und LastName festgelegt wurden. Aber was ist, wenn Sie lieber eine Methode hätten, um Eigenschaften zu setzen, die GetName() dann abrufen kann? In diesem Fall müssen Sie Methodenparameter definieren.

Definieren Sie Methodenparameter, indem Sie einen oder mehrere Parameter durch Kommas getrennt in den Methodenparameterklammern einschließen, wie unten gezeigt.

Beachten Sie den Ausgabetyp [void]. Wenn eine Methode nichts ausgibt, benötigen Sie keine return-Konstruktion, und Sie sollten den Ausgabetyp als [void] definieren, um PowerShell mitzuteilen, dass die Methode nichts zurückgibt.

[void]SetName([string]$Name) {

}

Zum Beispiel akzeptiert die Methode SetName() vielleicht einen vollständigen Namen (Vor- und Nachname). In diesem Fall können Sie diesen String im Skriptblock aufteilen und den Vor- und Nachnamen auf diese Weise zuweisen.

Indem Sie die Methode SetName() in die Klasse student einfügen, sieht sie nun folgendermaßen aus.

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]
    }
}

Jetzt können Sie einen vollständigen Namen als Parameter an die Methode SetName() übergeben, die die aktuellen Eigenschaften FirstName und LastName des Objekts festlegt.

Creating a class with a void method and showing the output when it is run.

Überladen von Methoden

Vielleicht möchten Sie verschiedene Parametergruppen für eine Methode definieren. Ähnlich wie bei Parametergruppen in Funktionen und Cmdlets können Sie verschiedene Parameter „Kontexte“ oder Methodensignaturen definieren.

Vielleicht möchten Sie die Parameter FirstName und LastName festlegen, indem Sie einen vollständigen Namen an die Methode SetName() übergeben oder den Vornamen und Nachnamen separat übergeben. Sie müssen nicht wählen; Sie können sie beide mit Methodensignaturen definieren.

Wenn Sie mehr als eine Methodensignatur in einer Klasse definieren, wird das Überladen genannt.

Unter Verwendung des Beispiels aus dem vorherigen Abschnitt können Sie eine Überladung für die Methode SetName() erstellen, um zwei Zeichenfolgen anstelle von einer zu akzeptieren. Wenn Sie zwei Zeichenfolgen anstelle von einer übergeben, geht die Methode SetName() davon aus, dass die erste Zeichenfolge der FirstName und die zweite Zeichenfolge der LastName ist. Mit dieser Überladung würde die Klasse wie folgt aussehen.

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
    }
}
Showing that the method overload works by providing either one or two strings.

Klassenkonstruktoren

Immer wenn Sie ein Objekt mit der Methode new() oder auf andere Weise instanziieren, können Sie PowerShell mitteilen, einige benutzerdefinierte Code, der als Konstruktor bezeichnet wird, auszuführen. Konstruktoren sind wie Methoden, werden jedoch automatisch ausgeführt, wenn PowerShell ein Objekt instanziiert.

Jede Klasse hat einen Standardkonstruktor. Dieser Standardkonstruktor tut nicht viel; er ist nur dafür verantwortlich, das Objekt zu instanziieren. Sie können den Standardkonstruktor anzeigen, indem Sie die Ausgabe der Methode New anzeigen. Sie können unten sehen, dass diese Zeile eine einzelne new() Methode zurückgibt.

[student]::New
Default PowerShell constructor

Konstruktorüberladen

Vielleicht möchten Sie einen Wert für die FirstName– und LastName-Eigenschaften festlegen, sobald Sie das Objekt erstellen, nicht mit der typischen Punktnotation. In diesem Fall können Sie einen Konstruktor mit einem Parameter erstellen, der dann SetName() aufruft.

Im Folgenden finden Sie ein Beispiel für einen Konstruktor für die Klasse student. Beachten Sie, dass der Konstruktor keinen spezifischen Namen hat und nicht mit einem Ausgabetyp versehen ist. Konstruktoren verwenden immer denselben Namen wie die Klasse.

Das Aufrufen einer vorhandenen Methode im Konstruktor ermöglicht es uns, die bereits geschriebene Methode wiederzuverwenden, um die Variablen zu setzen.

student([string]$Name) {
	$this.SetName($Name)
}

Und unten sehen Sie, wie dieser Konstruktor der Klasse student hinzugefügt wird.

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
    }
}

Wenn Sie ein neues student-Objekt instanziieren und einen Zeichenkettenparameter übergeben, werden die Eigenschaften des Objekts sofort die erwarteten Werte haben.

Showing the output from using the constructor with a string

Sie können nun den erneut überladenen Konstruktor mit [student]::New sehen. Beachten Sie nun, dass der neue überladene Konstruktor mit einem Name-Parameter definiert ist.

Overloaded constructor

Definition eines Standard- und überladenen Konstruktors

Jetzt, da Sie einen überladenen Konstruktor in Ihrer Klasse student haben, überschreibt PowerShell den Standardkonstruktor. Aber Sie können ihn zurückbekommen, indem Sie manuell einen ohne Parameter erstellen.

student() {}

Sie können sehen, wie das in der Klasse student aussieht.

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]
    }
}

Überprüfen Sie nun erneut die Konstruktoren. Sie sehen nun beide Konstruktoren erscheinen.

[student]::New
Creating a default and custom constructor

Klassenvererbung

Wie alle anderen objektorientierten Sprachen können Sie PowerShell-Klassen hierarchisch mit mehreren Klassen erstellen. Jede Klasse kann „übergeordnete“ und „untergeordnete“ Klassen haben, die von weniger spezifischen, generischeren Zwecken ausgehen und die Spezifität erhöhen.

Zum Beispiel repräsentiert unsere student-Klasse einen Universitätsstudenten (Kind/spezifisch). Dieser Universitätsstudent ist eine Person (Elternteil/generisch). Diese beiden Konzepte sind miteinander verbunden und bilden eine Hierarchie.

A child class can inherit a parent class which means it can hold all properties and methods (members) defined via a parent class. We know that a person class may have properties like eye_color, height, and weight and perhaps a method called SetHeight().

Wenn ein Student eine Person ist, hat dieser Student immer noch diese Eigenschaften und Methoden. Es wäre redundant, dieselben Member auf der student-Klasse zu implementieren, die die person-Klasse bereits hat. Sie können die Klassenvererbung definieren, um automatisch alle Member der person-Klasse auf der student-Klasse zu definieren.

Wenn das jetzt keinen Sinn ergibt, wird es das, wenn wir eine Demo durchgehen.

Demo zur Klassenvererbung

Zuerst erstellen Sie eine Kopie der student-Klasse, die Sie zuvor erstellt haben. Entfernen Sie die Konstruktoren und benennen Sie sie in eine person-Klasse um. Ihre person-Klasse sollte wie die untenstehende Klasse aussehen.

A student, of course, has a first name and last name, but the class can be described more accurately by labeling it as a person. When creating a more “generic” class like this, you can create more specific “child” classes from it.

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
    }
}

Erstellen Sie nun ein paar Klassen, die eine Person repräsentieren, aber eine spezifischere Rolle haben. Zum Beispiel haben Sie im folgenden Code-Snippet nun eine teacher– und eine student-Klasse.

class teacher {
    [int]$EmployeeId
}

class student {
    [int]$StudentId
}

So wie sie sind, sind die teacher– und student-Klassen voneinander unabhängig. Sie haben keine Beziehung, können jedoch keine Klassenmember der person-Klasse erben. Lassen Sie uns das ändern.

Jetzt definieren Sie diese Hierarchie, indem Sie die Lehrer und Schüler Klassen als „Kind“ Klassen der Person Klasse mit Vererbung definieren. Sie können die Vererbung definieren, indem Sie einen Doppelpunkt (:) nach dem Klassennamen anhängen, gefolgt vom Namen der Elternklasse wie unten gezeigt.

class teacher : person {
    [int]$EmployeeId
}

class student : person {
    [int]$StudentId
}

Ihr gesamtes Klassenskript sollte jetzt so aussehen:

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
}

Zu diesem Zeitpunkt, wenn Sie ein Objekt aus der Lehrer oder Schüler Klasse instantiieren, haben beide Klassen die gleichen Elemente wie die Person Klasse.

Class Inheritance Demo

Mit Konstruktoren vererben

Wie Sie oben gesehen haben, werden Klassenmethoden über Klassenvererbung vererbt. Dieses Verhalten könnte Sie dazu veranlassen zu denken, dass Konstruktoren dieser gleichen Logik folgen würden, aber das wäre falsch. Konstruktoren werden nicht vererbt, und Konstruktoren für alle Kindklassen müssen in jeder Kindklasse separat definiert werden.

Zum Beispiel haben Sie vielleicht gerade einen überladenen Konstruktor für die Person Klasse definiert, aber keinen Konstruktor für die Lehrer Klasse, wie unten gezeigt.

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

Dann definieren Sie eine Kindklasse, z.B. Lehrer, und versuchen, ein Objekt ohne Parameter daraus zu erstellen, wie unten gezeigt. Beachten Sie, dass PowerShell einen Fehler zurückgibt, weil ein parameterloser Konstruktor innerhalb der Lehrer Klasse nicht definiert wurde.

No class defined for child class

A constructor is not necessary in a child class if you’re only using it as a template. Alternatively, if you want to use the parent class as its own standalone class and as a parent class you can include constructors. But you have to make sure that the parent class has a constructor that matches the ones in the child classes.

Klassenmemberattribute

Genau wie PowerShell-Befehlsparameter können Klassen Mitgliedsattribute haben. Diese Attribute ändern das Verhalten jedes Mitglieds.

Versteckte Mitglieder

Wenn Sie ein Klassenmitglied nur für interne Zwecke verwenden und nicht möchten, dass der Benutzer darauf liest oder schreibt, können Sie ein Mitglied als versteckt festlegen. Zum Beispiel haben Sie möglicherweise eine Methode, die nur von anderen Methoden verwendet wird. Es ist nicht erforderlich, diese Methode dem Benutzer zugänglich zu machen.

Um ein verstecktes Element zu definieren, verwenden Sie das hidden-Attribut wie unten gezeigt.

class teacher {
    [int]hidden $EmployeeId
}

Wenn Sie nun Get-Member verwenden, um alle Objektmitglieder zu inspizieren, wird diese Eigenschaft nicht angezeigt.

Class Member Attributes

Das Festlegen eines Klassenmitglieds als versteckt beschränkt nicht den Zugriff auf den Wert; es verbirgt ihn nur. Sie sollten Eigenschaften nicht verbergen, um sensible Daten zu speichern.

Statische Mitglieder

Erinnern Sie sich an früher; dieses Tutorial verwendete den Begriff „instanziieren“, um die Erstellung eines Objekts aus einer Klasse zu beschreiben. Wenn Sie ein Objekt instanziieren, übernimmt dieses Objekt alle Eigenschaften und Methoden, die die Klasse definiert. Aber das ist nicht immer der Fall.

Manchmal benötigen Sie nicht den Overhead, ein ganzes Objekt zu instanziieren. Stattdessen müssen Sie schnell auf ein einzelnes Klassenmitglied verweisen. In diesem Fall können Sie ein Klassenmitglied als statisch setzen.

Genau wie beim hidden-Attribut definieren Sie ein Klassenmitglied als statisch unter Verwendung des Schlüsselworts static wie unten gezeigt.

class student {
	[int]static $MaxClassCount = 7
}

Anders als bei typischen Klassenmitgliedern erstellt PowerShell keine Eigenschaften und Methoden aus statischen Klassenmitgliedern. Wenn Sie ein Klassenmitglied als statisch definieren, wie versteckte Mitglieder, wird es nicht angezeigt, wenn Sie Get-Member verwenden.

Static Members

Zum Beispiel möchten Sie möglicherweise Universitätskursnamen mit der Klasse „student“ verknüpfen und die maximale Anzahl von Universitätskursen definieren, an denen ein Student teilnehmen kann. Dazu erstellen Sie ein „Classes“-Array-Mitglied und ein „MaxClassCount“-Mitglied.

Weil der Benutzer das „MaxClassCount“-Mitglied selten ändern muss, entscheiden Sie sich dazu, es als statisch zu definieren.

Schließlich erstellen Sie eine „AddClass()“ Methode, um einen Kurs zum Stundenplan des Studenten hinzuzufügen, aber nur wenn er kleiner als das „MaxClassCount“ ist.

class student {
    [string[]]$Classes = @()
    [int]static $MaxClassCount = 7
    
    [void]AddClass ([string]$Name) {
        if ($this.Classes.Count -lt [student]::MaxClassCount) {
            $this.Classes += $Name
        }
    }
}

Wenn Sie nun versuchen, ein neues „student“-Objekt zu erstellen und zu viele Universitätskurse zuzuweisen, weist PowerShell nur die maximale Anzahl zu, die sieben wäre.

$student1 = [student]::new()
'PE','English','Math','History','Computer Science','French','Wood Working','Cooking' | ForEach-Object {
	$student1.AddClass($_)
}
$student1.Classes
Class Count

Sie können die Werte von statischen Mitgliedern jederzeit ändern. Wenn Sie beispielsweise das „MaxClassCount“-Mitglied auf 5 anstelle von 7 setzen möchten, ändern Sie den Wert mit „[student]::MaxClassCount = 5“. Das Ändern des Werts würde in diesem Beispiel keine Kurse entfernen, die das Limit überschreiten.

Schlussfolgerung

PowerShell-Klassen verwischen die Grenze zwischen einer Skriptsprache und einer Programmiersprache. Klassen sind eine großartige Möglichkeit, Objektbeziehungen zu definieren, Möglichkeiten der Interaktion und Formatierung von Objekten hinzuzufügen, die normalerweise nur durch das Schreiben spezialisierter Funktionen möglich wären.

Source:
https://adamtheautomator.com/powershell-classes/