about_Classes
Krótki opis
Opisuje sposób używania klas do tworzenia własnych typów niestandardowych.
Długi opis
Począwszy od wersji 5.0, program PowerShell ma formalną składnię do definiowania klas i innych typów zdefiniowanych przez użytkownika. Dodanie klas umożliwia deweloperom i specjalistom IT korzystanie z programu PowerShell w szerszym zakresie przypadków użycia.
Deklaracja klasy jest strategią używaną do tworzenia wystąpień obiektów w czasie wykonywania. Podczas definiowania klasy nazwa klasy jest nazwą typu. Jeśli na przykład zadeklarujesz klasę o nazwie Device i zainicjujesz zmienną $dev
do nowego wystąpienia urządzenia, $dev
jest obiektem lub wystąpieniem typu Urządzenie. Każde wystąpienie urządzenia może mieć różne wartości we właściwościach.
Obsługiwane scenariusze
- Definiowanie typów niestandardowych w programie PowerShell przy użyciu semantyki programowania obiektowego, takich jak klasy, właściwości, metody, dziedziczenie itp.
- Zdefiniuj zasoby DSC i skojarzone z nimi typy przy użyciu języka programu PowerShell.
- Zdefiniuj atrybuty niestandardowe do dekorowania zmiennych, parametrów i niestandardowych definicji typów.
- Zdefiniuj niestandardowe wyjątki, które mogą być przechwytywane przez ich nazwę typu.
Składnia
Składnia definicji
Definicje klas używają następującej składni:
class <class-name> [: [<base-class>][,<interface-list>]] {
[[<attribute>] [hidden] [static] <property-definition> ...]
[<class-name>([<constructor-argument-list>])
{<constructor-statement-list>} ...]
[[<attribute>] [hidden] [static] <method-definition> ...]
}
Składnia wystąpienia
Aby utworzyć wystąpienie klasy, użyj jednej z następujących składni:
[$<variable-name> =] New-Object -TypeName <class-name> [
[-ArgumentList] <constructor-argument-list>]
[$<variable-name> =] [<class-name>]::new([<constructor-argument-list>])
[$<variable-name> =] [<class-name>]@{[<class-property-hashtable>]}
Uwaga
W przypadku używania [<class-name>]::new()
składni nawiasy wokół nazwy klasy są obowiązkowe. Nawiasy sygnalizujące definicję typu dla programu PowerShell.
Składnia skrótu działa tylko dla klas, które mają konstruktor domyślny, który nie oczekuje żadnych parametrów. Tworzy wystąpienie klasy z konstruktorem domyślnym, a następnie przypisuje pary klucz-wartość do właściwości wystąpienia. Jeśli jakikolwiek klucz w tabeli skrótu nie jest prawidłową nazwą właściwości, program PowerShell zgłasza błąd.
Przykłady
Przykład 1 — minimalna definicja
W tym przykładzie przedstawiono minimalną składnię wymaganą do utworzenia klasy użytecznej.
class Device {
[string]$Brand
}
$dev = [Device]::new()
$dev.Brand = "Fabrikam, Inc."
$dev
Brand
-----
Fabrikam, Inc.
Przykład 2 — Klasa z elementami członkowskimi wystąpienia
W tym przykładzie zdefiniowano klasę Book z kilkoma właściwościami, konstruktorami i metodami. Każdy zdefiniowany element członkowski jest członkiem wystąpienia , a nie statycznym elementem członkowskim. Dostęp do właściwości i metod można uzyskać tylko za pośrednictwem utworzonego wystąpienia klasy.
class Book {
# Class properties
[string] $Title
[string] $Author
[string] $Synopsis
[string] $Publisher
[datetime] $PublishDate
[int] $PageCount
[string[]] $Tags
# Default constructor
Book() { $this.Init(@{}) }
# Convenience constructor from hashtable
Book([hashtable]$Properties) { $this.Init($Properties) }
# Common constructor for title and author
Book([string]$Title, [string]$Author) {
$this.Init(@{Title = $Title; Author = $Author })
}
# Shared initializer method
[void] Init([hashtable]$Properties) {
foreach ($Property in $Properties.Keys) {
$this.$Property = $Properties.$Property
}
}
# Method to calculate reading time as 2 minutes per page
[timespan] GetReadingTime() {
if ($this.PageCount -le 0) {
throw 'Unable to determine reading time from page count.'
}
$Minutes = $this.PageCount * 2
return [timespan]::new(0, $Minutes, 0)
}
# Method to calculate how long ago a book was published
[timespan] GetPublishedAge() {
if (
$null -eq $this.PublishDate -or
$this.PublishDate -eq [datetime]::MinValue
) { throw 'PublishDate not defined' }
return (Get-Date) - $this.PublishDate
}
# Method to return a string representation of the book
[string] ToString() {
return "$($this.Title) by $($this.Author) ($($this.PublishDate.Year))"
}
}
Poniższy fragment kodu tworzy wystąpienie klasy i pokazuje, jak się zachowuje. Po utworzeniu wystąpienia klasy Book przykład używa GetReadingTime()
metod i GetPublishedAge()
do pisania komunikatu o książce.
$Book = [Book]::new(@{
Title = 'The Hobbit'
Author = 'J.R.R. Tolkien'
Publisher = 'George Allen & Unwin'
PublishDate = '1937-09-21'
PageCount = 310
Tags = @('Fantasy', 'Adventure')
})
$Book
$Time = $Book.GetReadingTime()
$Time = @($Time.Hours, 'hours and', $Time.Minutes, 'minutes') -join ' '
$Age = [Math]::Floor($Book.GetPublishedAge().TotalDays / 365.25)
"It takes $Time to read $Book,`nwhich was published $Age years ago."
Title : The Hobbit
Author : J.R.R. Tolkien
Synopsis :
Publisher : George Allen & Unwin
PublishDate : 9/21/1937 12:00:00 AM
PageCount : 310
Tags : {Fantasy, Adventure}
It takes 10 hours and 20 minutes to read The Hobbit by J.R.R. Tolkien (1937),
which was published 86 years ago.
Przykład 3 — Klasa ze statycznymi elementami członkowskimi
Klasa BookList w tym przykładzie opiera się na klasie Book w przykładzie 2. Chociaż klasa BookList nie może być oznaczona jako statyczna, implementacja definiuje tylko właściwość statyczną Books i zestaw metod statycznych do zarządzania tą właściwością.
class BookList {
# Static property to hold the list of books
static [System.Collections.Generic.List[Book]] $Books
# Static method to initialize the list of books. Called in the other
# static methods to avoid needing to explicit initialize the value.
static [void] Initialize() { [BookList]::Initialize($false) }
static [bool] Initialize([bool]$force) {
if ([BookList]::Books.Count -gt 0 -and -not $force) {
return $false
}
[BookList]::Books = [System.Collections.Generic.List[Book]]::new()
return $true
}
# Ensure a book is valid for the list.
static [void] Validate([book]$Book) {
$Prefix = @(
'Book validation failed: Book must be defined with the Title,'
'Author, and PublishDate properties, but'
) -join ' '
if ($null -eq $Book) { throw "$Prefix was null" }
if ([string]::IsNullOrEmpty($Book.Title)) {
throw "$Prefix Title wasn't defined"
}
if ([string]::IsNullOrEmpty($Book.Author)) {
throw "$Prefix Author wasn't defined"
}
if ([datetime]::MinValue -eq $Book.PublishDate) {
throw "$Prefix PublishDate wasn't defined"
}
}
# Static methods to manage the list of books.
# Add a book if it's not already in the list.
static [void] Add([Book]$Book) {
[BookList]::Initialize()
[BookList]::Validate($Book)
if ([BookList]::Books.Contains($Book)) {
throw "Book '$Book' already in list"
}
$FindPredicate = {
param([Book]$b)
$b.Title -eq $Book.Title -and
$b.Author -eq $Book.Author -and
$b.PublishDate -eq $Book.PublishDate
}.GetNewClosure()
if ([BookList]::Books.Find($FindPredicate)) {
throw "Book '$Book' already in list"
}
[BookList]::Books.Add($Book)
}
# Clear the list of books.
static [void] Clear() {
[BookList]::Initialize()
[BookList]::Books.Clear()
}
# Find a specific book using a filtering scriptblock.
static [Book] Find([scriptblock]$Predicate) {
[BookList]::Initialize()
return [BookList]::Books.Find($Predicate)
}
# Find every book matching the filtering scriptblock.
static [Book[]] FindAll([scriptblock]$Predicate) {
[BookList]::Initialize()
return [BookList]::Books.FindAll($Predicate)
}
# Remove a specific book.
static [void] Remove([Book]$Book) {
[BookList]::Initialize()
[BookList]::Books.Remove($Book)
}
# Remove a book by property value.
static [void] RemoveBy([string]$Property, [string]$Value) {
[BookList]::Initialize()
$Index = [BookList]::Books.FindIndex({
param($b)
$b.$Property -eq $Value
}.GetNewClosure())
if ($Index -ge 0) {
[BookList]::Books.RemoveAt($Index)
}
}
}
Teraz, gdy lista BookList jest zdefiniowana, do listy można dodać książkę z poprzedniego przykładu.
$null -eq [BookList]::Books
[BookList]::Add($Book)
[BookList]::Books
True
Title : The Hobbit
Author : J.R.R. Tolkien
Synopsis :
Publisher : George Allen & Unwin
PublishDate : 9/21/1937 12:00:00 AM
PageCount : 310
Tags : {Fantasy, Adventure}
Poniższy fragment kodu wywołuje metody statyczne dla klasy.
[BookList]::Add([Book]::new(@{
Title = 'The Fellowship of the Ring'
Author = 'J.R.R. Tolkien'
Publisher = 'George Allen & Unwin'
PublishDate = '1954-07-29'
PageCount = 423
Tags = @('Fantasy', 'Adventure')
}))
[BookList]::Find({
param ($b)
$b.PublishDate -gt '1950-01-01'
}).Title
[BookList]::FindAll({
param($b)
$b.Author -match 'Tolkien'
}).Title
[BookList]::Remove($Book)
[BookList]::Books.Title
[BookList]::RemoveBy('Author', 'J.R.R. Tolkien')
"Titles: $([BookList]::Books.Title)"
[BookList]::Add($Book)
[BookList]::Add($Book)
The Fellowship of the Ring
The Hobbit
The Fellowship of the Ring
The Fellowship of the Ring
Titles:
Book 'The Hobbit by J.R.R. Tolkien (1937)' already in list
At C:\code\classes.examples.ps1:114 char:13
+ throw "Book '$Book' already in list"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (Book 'The Hobbi...alread
y in list:String) [], RuntimeException
+ FullyQualifiedErrorId : Book 'The Hobbit by J.R.R. Tolkien (1937)'
already in list
Właściwości klasy
Właściwości to zmienne zadeklarowane w zakresie klasy. Właściwość może mieć dowolny typ wbudowany lub wystąpienie innej klasy. Klasy mogą mieć zero lub więcej właściwości. Klasy nie mają maksymalnej liczby właściwości.
Aby uzyskać więcej informacji, zobacz about_Classes_Properties.
Metody klas
Metody definiują akcje, które może wykonywać klasa. Metody mogą przyjmować parametry określające dane wejściowe. Metody zawsze definiują typ danych wyjściowych. Jeśli metoda nie zwraca żadnych danych wyjściowych, musi mieć typ danych wyjściowych Void . Jeśli metoda nie definiuje jawnie typu danych wyjściowych, typ danych wyjściowych metody to Void.
Aby uzyskać więcej informacji, zobacz about_Classes_Methods.
Konstruktory klas
Konstruktory umożliwiają ustawianie wartości domyślnych i weryfikowanie logiki obiektu w momencie tworzenia wystąpienia klasy. Konstruktory mają taką samą nazwę jak klasa. Konstruktory mogą mieć parametry, aby zainicjować elementy członkowskie danych nowego obiektu.
Aby uzyskać więcej informacji, zobacz about_Classes_Constructors.
Ukryte słowo kluczowe
Słowo hidden
kluczowe ukrywa składową klasy. Element członkowski jest nadal dostępny dla użytkownika i jest dostępny we wszystkich zakresach, w których obiekt jest dostępny.
Ukryte elementy członkowskie są ukryte przed poleceniem Get-Member
cmdlet i nie można ich wyświetlić przy użyciu uzupełniania kart ani funkcji IntelliSense poza definicją klasy.
Słowo hidden
kluczowe dotyczy tylko składowych klasy, a nie samej klasy.
Ukryte składowe klasy to:
- Nieuwzględniane w domyślnych danych wyjściowych klasy.
- Nieuwzględniane na liście składowych klas zwracanych przez
Get-Member
polecenie cmdlet. Aby wyświetlić ukryte elementy członkowskie za pomocąGet-Member
polecenia , użyj parametru Force . - Nie są wyświetlane w uzupełnianiu karty lub funkcji IntelliSense, chyba że ukończenie występuje w klasie definiującej ukryty element członkowski.
- Publiczne elementy członkowskie klasy. Można uzyskać do nich dostęp, dziedziczyć i modyfikować. Ukrywanie elementu członkowskiego nie powoduje, że jest on prywatny. Ukrywa on tylko element członkowski zgodnie z opisem w poprzednich punktach.
Uwaga
Po ukryciu przeciążenia metody ta metoda zostanie usunięta z funkcji IntelliSense, wyników ukończenia i domyślnych danych wyjściowych dla metody Get-Member
.
Po ukryciu dowolnego konstruktora new()
opcja zostanie usunięta z funkcji IntelliSense i wyników ukończenia.
Aby uzyskać więcej informacji na temat słowa kluczowego, zobacz about_Hidden. Aby uzyskać więcej informacji na temat ukrytych właściwości, zobacz about_Classes_Properties. Aby uzyskać więcej informacji na temat ukrytych metod, zobacz about_Classes_Methods. Aby uzyskać więcej informacji na temat ukrytych konstruktorów, zobacz about_Classes_Constructors.
Słowo kluczowe statyczne
Słowo static
kluczowe definiuje właściwość lub metodę, która istnieje w klasie i nie wymaga wystąpienia.
Właściwość statyczna jest zawsze dostępna, niezależnie od wystąpienia klasy. Właściwość statyczna jest współdzielona we wszystkich wystąpieniach klasy. Metoda statyczna jest zawsze dostępna. Wszystkie właściwości statyczne są aktywne dla całego zakresu sesji.
Słowo static
kluczowe dotyczy tylko składowych klasy, a nie samej klasy.
Aby uzyskać więcej informacji na temat właściwości statycznych, zobacz about_Classes_Properties. Aby uzyskać więcej informacji na temat metod statycznych, zobacz about_Classes_Methods. Aby uzyskać więcej informacji na temat konstruktorów statycznych, zobacz about_Classes_Constructors.
Dziedziczenie w klasach programu PowerShell
Klasę można rozszerzyć, tworząc nową klasę pochodzącą z istniejącej klasy. Klasa pochodna dziedziczy właściwości i metody klasy bazowej. Możesz dodać lub zastąpić składowe klasy bazowej zgodnie z wymaganiami.
Program PowerShell nie obsługuje wielu dziedziczenia. Klasy nie mogą dziedziczyć bezpośrednio z więcej niż jednej klasy.
Klasy mogą również dziedziczyć z interfejsów, które definiują kontrakt. Klasa dziedziczona z interfejsu musi implementować ten kontrakt. W takim przypadku klasa może być używana jak każda inna klasa implementujący ten interfejs.
Aby uzyskać więcej informacji na temat klas pochodnych, które dziedziczą z klasy bazowej lub implementują interfejsy, zobacz about_Classes_Inheritance.
Eksportowanie klas z akceleratorami typów
Domyślnie moduły programu PowerShell nie eksportują automatycznie klas i wyliczeń zdefiniowanych w programie PowerShell. Typy niestandardowe nie są dostępne poza modułem bez wywoływania instrukcji using module
.
Jeśli jednak moduł dodaje akceleratory typów, akceleratory tego typu są natychmiast dostępne w sesji po zaimportowaniu modułu przez użytkowników.
Uwaga
Dodawanie akceleratorów typów do sesji używa wewnętrznego (nie publicznego) interfejsu API. Użycie tego interfejsu API może powodować konflikty. Wzorzec opisany poniżej zgłasza błąd, jeśli akcelerator typu o tej samej nazwie już istnieje podczas importowania modułu. Usuwa również akceleratory typów podczas usuwania modułu z sesji.
Ten wzorzec gwarantuje, że typy są dostępne w sesji. Nie ma to wpływu na funkcję IntelliSense ani uzupełnianie podczas tworzenia pliku skryptu w programie VS Code.
Aby uzyskać sugestie dotyczące funkcji IntelliSense i uzupełniania dla typów niestandardowych w programie VS Code, należy dodać instrukcję using module
na początku skryptu.
Poniższy wzorzec pokazuje, jak zarejestrować klasy programu PowerShell i wyliczenia jako akceleratory typów w module. Dodaj fragment kodu do modułu skryptu głównego po dowolnych definicjach typów. Upewnij się, że zmienna $ExportableTypes
zawiera każdy z typów, które mają być dostępne dla użytkowników podczas importowania modułu. Drugi kod nie wymaga edycji.
# Define the types to export with type accelerators.
$ExportableTypes =@(
[DefinedTypeName]
)
# Get the internal TypeAccelerators class to use its static methods.
$TypeAcceleratorsClass = [psobject].Assembly.GetType(
'System.Management.Automation.TypeAccelerators'
)
# Ensure none of the types would clobber an existing type accelerator.
# If a type accelerator with the same name exists, throw an exception.
$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get
foreach ($Type in $ExportableTypes) {
if ($Type.FullName -in $ExistingTypeAccelerators.Keys) {
$Message = @(
"Unable to register type accelerator '$($Type.FullName)'"
'Accelerator already exists.'
) -join ' - '
throw [System.Management.Automation.ErrorRecord]::new(
[System.InvalidOperationException]::new($Message),
'TypeAcceleratorAlreadyExists',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$Type.FullName
)
}
}
# Add type accelerators for every exportable type.
foreach ($Type in $ExportableTypes) {
$TypeAcceleratorsClass::Add($Type.FullName, $Type)
}
# Remove type accelerators when the module is removed.
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
foreach($Type in $ExportableTypes) {
$TypeAcceleratorsClass::Remove($Type.FullName)
}
}.GetNewClosure()
Podczas importowania modułu przez użytkowników wszystkie typy dodane do akceleratorów typów dla sesji są natychmiast dostępne dla funkcji IntelliSense i uzupełniania. Po usunięciu modułu są więc akceleratory typów.
Ręczne importowanie klas z modułu programu PowerShell
Import-Module
i instrukcja #requires
importuje tylko funkcje modułu, aliasy i zmienne, zgodnie z definicją w module. Klasy nie są importowane.
Jeśli moduł definiuje klasy i wyliczenia, ale nie dodaje akceleratorów typów dla tych typów, użyj using module
instrukcji , aby je zaimportować.
Instrukcja using module
importuje klasy i wyliczenia z modułu głównego (ModuleToProcess
) modułu skryptu lub modułu binarnego. Nie importuje spójnie klas zdefiniowanych w zagnieżdżonych modułach ani klasach zdefiniowanych w skryptach, które są dot-source do modułu głównego. Zdefiniuj klasy, które mają być dostępne dla użytkowników spoza modułu bezpośrednio w module głównym.
Aby uzyskać więcej informacji na temat instrukcji using
, zobacz about_Using.
Ładowanie nowo zmienionego kodu podczas programowania
Podczas opracowywania modułu skryptu często wprowadza się zmiany w kodzie, a następnie ładują nową wersję modułu przy użyciu Import-Module
parametru Force . Ponowne ładowanie modułu działa tylko w przypadku zmian funkcji w module głównym. Import-Module
nie ładuje ponownie żadnych zagnieżdżonych modułów. Ponadto nie ma możliwości załadowania zaktualizowanych klas.
Aby upewnić się, że używasz najnowszej wersji, musisz uruchomić nową sesję.
Nie można zwolnić klas i wyliczenia zdefiniowanych w programie PowerShell i zaimportowanych za pomocą using
instrukcji.
Innym typowym rozwiązaniem programistycznym jest rozdzielenie kodu na różne pliki. Jeśli masz funkcję w jednym pliku, który używa klas zdefiniowanych w innym module, należy użyć using module
instrukcji , aby upewnić się, że funkcje mają wymagane definicje klas.
Typ PSReference nie jest obsługiwany z elementami członkowskimi klasy
Akcelerator [ref]
typu jest skrótem dla klasy PSReference . Używanie [ref]
metody do rzutowania typu składowej klasy kończy się niepowodzeniem w trybie dyskretnym. Interfejsy API używające [ref]
parametrów nie mogą być używane z elementami członkowskimi klasy. Klasa PSReference została zaprojektowana do obsługi obiektów COM. Obiekty COM mają przypadki, w których należy przekazać wartość w odwołaniu.
Aby uzyskać więcej informacji, zobacz Klasa PSReference.
Ograniczenia
Poniższe listy zawierają ograniczenia dotyczące definiowania klas programu PowerShell i obejścia tych ograniczeń, jeśli istnieją.
Ogólne ograniczenia
Składowe klasy nie mogą używać funkcji PSReference jako ich typu.
Obejście: brak.
Nie można zwolnić ani ponownie załadować klas programu PowerShell w sesji.
Obejście: Rozpocznij nową sesję.
Klasy programu PowerShell zdefiniowane w module nie są importowane automatycznie.
Obejście: Dodaj zdefiniowane typy do listy akceleratorów typów w module głównym. Dzięki temu typy są dostępne podczas importowania modułów.
Słowa
hidden
kluczowe istatic
dotyczą tylko składowych klas, a nie definicji klasy.Obejście: brak.
Ograniczenia konstruktora
Łańcuch konstruktora nie jest implementowany.
Obejście: Zdefiniuj ukryte
Init()
metody i wywołaj je z poziomu konstruktorów.Parametry konstruktora nie mogą używać żadnych atrybutów, w tym atrybutów walidacji.
Obejście: Przypisz ponownie parametry w treści konstruktora za pomocą atrybutu weryfikacji.
Parametry konstruktora nie mogą definiować wartości domyślnych. Parametry są zawsze obowiązkowe.
Obejście: brak.
Jeśli jakiekolwiek przeciążenie konstruktora jest ukryte, każde przeciążenie konstruktora jest również traktowane jako ukryte.
Obejście: brak.
Ograniczenia metody
Parametry metody nie mogą używać żadnych atrybutów, w tym atrybutów walidacji.
Obejście: Przypisz ponownie parametry w treści metody za pomocą atrybutu weryfikacji lub zdefiniuj metodę w konstruktorze statycznym za pomocą
Update-TypeData
polecenia cmdlet .Parametry metody nie mogą definiować wartości domyślnych. Parametry są zawsze obowiązkowe.
Obejście: Zdefiniuj metodę w konstruktorze statycznym za pomocą
Update-TypeData
polecenia cmdlet .Metody są zawsze publiczne, nawet jeśli są ukryte. Można je przesłonić, gdy klasa jest dziedziczona.
Obejście: brak.
Jeśli jakiekolwiek przeciążenie metody jest ukryte, każde przeciążenie tej metody jest również traktowane jako ukryte.
Obejście: brak.
Ograniczenia właściwości
Właściwości statyczne są zawsze modyfikowalne. Klasy programu PowerShell nie mogą definiować niezmiennych właściwości statycznych.
Obejście: brak.
Właściwości nie mogą używać atrybutu ValidateScript , ponieważ argumenty atrybutu właściwości klasy muszą być stałe.
Obejście: Zdefiniuj klasę dziedziczą z typu ValidateArgumentsAttribute i użyj tego atrybutu.
Właściwości zadeklarowane bezpośrednio nie mogą definiować niestandardowych implementacji getter i setter.
Obejście: Zdefiniuj właściwość ukrytą i użyj polecenia
Update-TypeData
, aby zdefiniować widoczną logikę pobierania i ustawiania.Właściwości nie mogą używać atrybutu Alias . Atrybut dotyczy tylko parametrów, poleceń cmdlet i funkcji.
Obejście: Użyj
Update-TypeData
polecenia cmdlet, aby zdefiniować aliasy w konstruktorach klas.Po przekonwertowaniu klasy programu PowerShell na kod JSON za
ConvertTo-Json
pomocą polecenia cmdlet dane wyjściowe JSON zawierają wszystkie ukryte właściwości i ich wartości.Obejście: brak
Ograniczenia dziedziczenia
Program PowerShell nie obsługuje definiowania interfejsów w kodzie skryptu.
Obejście: Zdefiniuj interfejsy w języku C# i odwołuj się do zestawu, który definiuje interfejsy.
Klasy programu PowerShell mogą dziedziczyć tylko z jednej klasy bazowej.
Obejście: Dziedziczenie klas jest przechodnie. Klasa pochodna może dziedziczyć z innej klasy pochodnej, aby uzyskać właściwości i metody klasy bazowej.
Podczas dziedziczenia z klasy ogólnej lub interfejsu należy już zdefiniować parametr typu dla klasy ogólnej. Klasa nie może zdefiniować się jako parametr typu dla klasy lub interfejsu.
Obejście: Aby pochodzić z ogólnej klasy bazowej lub interfejsu, zdefiniuj typ niestandardowy w innym
.psm1
pliku i użyjusing module
instrukcji , aby załadować typ. Nie ma obejścia dla typu niestandardowego, aby używać go jako parametru typu podczas dziedziczenia po typie ogólnym.