Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Deskripsi singkat
Menjelaskan bagaimana Anda dapat menentukan kelas yang memperluas jenis lain.
Deskripsi panjang
Kelas PowerShell mendukung warisan, yang memungkinkan Anda menentukan kelas turunan yang menggunakan kembali (mewarisi), memperluas, atau memodifikasi perilaku kelas induk. Kelas yang anggotanya diwariskan disebut kelas dasar . Kelas yang mewarisi anggota kelas dasar disebut kelas turunan .
PowerShell hanya mendukung pewarisan tunggal. Sebuah kelas hanya dapat mewarisi dari satu kelas. Namun, pewarisan bersifat transitif, yang memungkinkan Anda menentukan hierarki warisan untuk sekumpulan jenis. Dengan kata lain, jenis D dapat mewarisi dari jenis C, yang mewarisi dari jenis B, yang mewarisi dari jenis kelas dasar A. Karena pewarisan bersifat transitif, anggota jenis A tersedia untuk jenis D.
Kelas turunan tidak mewarisi semua anggota kelas dasar. Anggota berikut ini tidak diwariskan:
- Konstruktor statis, yang menginisialisasi data statis kelas.
- Konstruktor instans, yang Anda panggil untuk membuat instans baru dari kelas. Setiap kelas harus mendefinisikan konstruktornya sendiri.
Anda dapat memperluas kelas dengan membuat kelas baru yang berasal dari kelas yang ada. Kelas turunan mewarisi properti dan metode kelas dasar. Anda dapat menambahkan atau mengambil alih anggota kelas dasar sesuai kebutuhan.
Kelas juga dapat mewarisi dari antarmuka, yang menentukan kontrak. Kelas yang mewarisi dari antarmuka harus mengimplementasikan kontrak tersebut. Ketika itu terjadi, kelas dapat digunakan seperti kelas lain yang mengimplementasikan antarmuka tersebut. Jika kelas mewarisi dari antarmuka tetapi tidak mengimplementasikan antarmuka, PowerShell menimbulkan kesalahan penguraian untuk kelas tersebut.
Beberapa operator PowerShell bergantung pada kelas yang menerapkan antarmuka tertentu.
Misalnya, operator
Kelas turunan menggunakan sintaks : untuk memperluas kelas dasar atau mengimplementasikan antarmuka. Kelas turunan harus selalu berada di paling kiri dalam deklarasi kelas.
Contoh ini memperlihatkan sintaks pewarisan kelas PowerShell dasar.
class Derived : Base {...}
Contoh ini menunjukkan pewarisan dengan deklarasi antarmuka yang datang setelah kelas dasar.
class Derived : Base, Interface {...}
Syntax
Pewarisan kelas menggunakan sintaks berikut:
Sintaks satu baris
class <derived-class-name> : <base-class-or-interface-name>[, <interface-name>...] {
<derived-class-body>
}
Misalnya:
# Base class only
class Derived : Base {...}
# Interface only
class Derived : System.IComparable {...}
# Base class and interface
class Derived : Base, System.IComparable {...}
Sintaksis Banyak Baris
class <derived-class-name> : <base-class-or-interface-name>[,
<interface-name>...] {
<derived-class-body>
}
Misalnya:
class Derived : Base,
System.IComparable,
System.IFormattable,
System.IConvertible {
# Derived class definition
}
Examples
Contoh 1 - Mewarisi dan mengambil alih dari kelas dasar
Contoh berikut menunjukkan perilaku properti yang diwariskan dengan dan tanpa mengambil alih. Jalankan blok kode secara berurutan setelah membaca deskripsinya.
Menentukan kelas dasar
Blok kode pertama mendefinisikan PublishedWork sebagai kelas dasar. Ini memiliki dua properti statis, List dan Artists. Selanjutnya, mendefinisikan metode statis RegisterWork() untuk menambahkan karya ke properti Daftar statis dan artis ke properti Artis , sambil menulis pesan untuk setiap entri baru dalam daftar tersebut.
Kelas mendefinisikan tiga properti instans yang menggambarkan sebuah karya yang diterbitkan.
Terakhir, ini mendefinisikan metode instans Register() dan ToString().
class PublishedWork {
static [PublishedWork[]] $List = @()
static [string[]] $Artists = @()
static [void] RegisterWork([PublishedWork]$Work) {
$wName = $Work.Name
$wArtist = $Work.Artist
if ($Work -notin [PublishedWork]::List) {
Write-Verbose "Adding work '$wName' to works list"
[PublishedWork]::List += $Work
} else {
Write-Verbose "Work '$wName' already registered."
}
if ($wArtist -notin [PublishedWork]::Artists) {
Write-Verbose "Adding artist '$wArtist' to artists list"
[PublishedWork]::Artists += $wArtist
} else {
Write-Verbose "Artist '$wArtist' already registered."
}
}
static [void] ClearRegistry() {
Write-Verbose "Clearing PublishedWork registry"
[PublishedWork]::List = @()
[PublishedWork]::Artists = @()
}
[string] $Name
[string] $Artist
[string] $Category
[void] Init([string]$WorkType) {
if ([string]::IsNullOrEmpty($this.Category)) {
$this.Category = "${WorkType}s"
}
}
PublishedWork() {
$WorkType = $this.GetType().FullName
$this.Init($WorkType)
Write-Verbose "Defined a published work of type [$WorkType]"
}
PublishedWork([string]$Name, [string]$Artist) {
$WorkType = $this.GetType().FullName
$this.Name = $Name
$this.Artist = $Artist
$this.Init($WorkType)
Write-Verbose "Defined '$Name' by $Artist as a published work of type [$WorkType]"
}
PublishedWork([string]$Name, [string]$Artist, [string]$Category) {
$WorkType = $this.GetType().FullName
$this.Name = $Name
$this.Artist = $Artist
$this.Init($WorkType)
Write-Verbose "Defined '$Name' by $Artist ($Category) as a published work of type [$WorkType]"
}
[void] Register() { [PublishedWork]::RegisterWork($this) }
[string] ToString() { return "$($this.Name) by $($this.Artist)" }
}
Menentukan kelas turunan tanpa penimpaan
Kelas turunan pertama adalah Album. Ini tidak menggantikan properti atau metode apa pun. Ini menambahkan properti instans baru, Genre, yang tidak ada di kelas dasar.
class Album : PublishedWork {
[string[]] $Genres = @()
}
Blok kode berikut menunjukkan perilaku kelas Album $VerbosePreference sehingga pesan dari metode kelas mengirimkan ke konsol. Ini membuat tiga instans kelas, menunjukkannya dalam tabel, lalu mendaftarkannya dengan metode RegisterWork() statis yang diwariskan. Kemudian memanggil metode statis yang sama pada kelas dasar secara langsung.
$VerbosePreference = 'Continue'
$Albums = @(
[Album]@{
Name = 'The Dark Side of the Moon'
Artist = 'Pink Floyd'
Genres = 'Progressive rock', 'Psychedelic rock'
}
[Album]@{
Name = 'The Wall'
Artist = 'Pink Floyd'
Genres = 'Progressive rock', 'Art rock'
}
[Album]@{
Name = '36 Chambers'
Artist = 'Wu-Tang Clan'
Genres = 'Hip hop'
}
)
$Albums | Format-Table
$Albums | ForEach-Object { [Album]::RegisterWork($_) }
$Albums | ForEach-Object { [PublishedWork]::RegisterWork($_) }
VERBOSE: Defined a published work of type [Album]
VERBOSE: Defined a published work of type [Album]
VERBOSE: Defined a published work of type [Album]
Genres Name Artist Category
------ ---- ------ --------
{Progressive rock, Psychedelic rock} The Dark Side of the Moon Pink Floyd Albums
{Progressive rock, Art rock} The Wall Pink Floyd Albums
{Hip hop} 36 Chambers Wu-Tang Clan Albums
VERBOSE: Adding work 'The Dark Side of the Moon' to works list
VERBOSE: Adding artist 'Pink Floyd' to artists list
VERBOSE: Adding work 'The Wall' to works list
VERBOSE: Artist 'Pink Floyd' already registered.
VERBOSE: Adding work '36 Chambers' to works list
VERBOSE: Adding artist 'Wu-Tang Clan' to artists list
VERBOSE: Work 'The Dark Side of the Moon' already registered.
VERBOSE: Artist 'Pink Floyd' already registered.
VERBOSE: Work 'The Wall' already registered.
VERBOSE: Artist 'Pink Floyd' already registered.
VERBOSE: Work '36 Chambers' already registered.
VERBOSE: Artist 'Wu-Tang Clan' already registered.
Perhatikan bahwa meskipun kelas Album
Dalam pesan mendetail, panggilan kedua ke metode RegisterWork() menyatakan bahwa karya dan seniman sudah terdaftar. Meskipun panggilan pertama ke
Blok kode berikutnya menghapus registri dan memanggil metode instans
[PublishedWork]::ClearRegistry()
$Albums.Register()
VERBOSE: Clearing PublishedWork registry
VERBOSE: Adding work 'The Dark Side of the Moon' to works list
VERBOSE: Adding artist 'Pink Floyd' to artists list
VERBOSE: Adding work 'The Wall' to works list
VERBOSE: Artist 'Pink Floyd' already registered.
VERBOSE: Adding work '36 Chambers' to works list
VERBOSE: Adding artist 'Wu-Tang Clan' to artists list
Metode instans pada objek Album
Blok kode berikut membandingkan properti statis untuk kelas dasar dan kelas turunan, yang menunjukkan bahwa mereka sama.
[pscustomobject]@{
'[PublishedWork]::List' = [PublishedWork]::List -join ",`n"
'[Album]::List' = [Album]::List -join ",`n"
'[PublishedWork]::Artists' = [PublishedWork]::Artists -join ",`n"
'[Album]::Artists' = [Album]::Artists -join ",`n"
'IsSame::List' = (
[PublishedWork]::List.Count -eq [Album]::List.Count -and
[PublishedWork]::List.ToString() -eq [Album]::List.ToString()
)
'IsSame::Artists' = (
[PublishedWork]::Artists.Count -eq [Album]::Artists.Count -and
[PublishedWork]::Artists.ToString() -eq [Album]::Artists.ToString()
)
} | Format-List
[PublishedWork]::List : The Dark Side of the Moon by Pink Floyd,
The Wall by Pink Floyd,
36 Chambers by Wu-Tang Clan
[Album]::List : The Dark Side of the Moon by Pink Floyd,
The Wall by Pink Floyd,
36 Chambers by Wu-Tang Clan
[PublishedWork]::Artists : Pink Floyd,
Wu-Tang Clan
[Album]::Artists : Pink Floyd,
Wu-Tang Clan
IsSame::List : True
IsSame::Artists : True
Menentukan kelas turunan dengan penimpaan
Blok kode berikutnya mendefinisikan kelas Ilustrasi yang diwarisi dari kelas dasar PublishedWork. Kelas baru memperluas kelas dasar dengan menentukan properti instans Medium dengan nilai default Unknown.
Tidak seperti kelas Album turunan
- Ini mengambil alih properti Artis
statis. Definisinya sama, tetapi kelas Ilustrasi menyatakannya secara langsung. - Ini mengambil alih properti instans Kategori
, mengatur nilai default ke . - Ini mengganti metode instans
ToString()sehingga representasi string dari ilustrasi mencakup medium yang digunakan untuk membuatnya.
Kelas ini juga mendefinisikan metode RegisterIllustration() statis untuk terlebih dahulu memanggil metode RegisterWork() dari kelas dasar dan kemudian menambahkan artist ke properti statis Artists yang dioverride pada kelas turunan.
Sebagai kesimpulan, kelas mengganti semua tiga konstruktor:
- Konstruktor bawaan kosong kecuali terdapat pesan yang menjelaskan bahwa ia membuat ilustrasi.
- Konstruktor berikutnya mengambil dua nilai string untuk nama dan artis yang membuat ilustrasi. Alih-alih menerapkan logika untuk mengatur properti Nama dan Artist, konstruktor memanggil konstruktor yang sesuai dari kelas dasar.
- Konstruktor terakhir mengambil tiga nilai string untuk nama, artis, dan medium ilustrasi. Kedua konstruktor menulis pesan verbose yang menunjukkan bahwa mereka membuat ilustrasi.
class Illustration : PublishedWork {
static [string[]] $Artists = @()
static [void] RegisterIllustration([Illustration]$Work) {
$wArtist = $Work.Artist
[PublishedWork]::RegisterWork($Work)
if ($wArtist -notin [Illustration]::Artists) {
Write-Verbose "Adding illustrator '$wArtist' to artists list"
[Illustration]::Artists += $wArtist
} else {
Write-Verbose "Illustrator '$wArtist' already registered."
}
}
[string] $Category = 'Illustrations'
[string] $Medium = 'Unknown'
[string] ToString() {
return "$($this.Name) by $($this.Artist) ($($this.Medium))"
}
Illustration() {
Write-Verbose 'Defined an illustration'
}
Illustration([string]$Name, [string]$Artist) : base($Name, $Artist) {
Write-Verbose "Defined '$Name' by $Artist ($($this.Medium)) as an illustration"
}
Illustration([string]$Name, [string]$Artist, [string]$Medium) {
$this.Name = $Name
$this.Artist = $Artist
$this.Medium = $Medium
Write-Verbose "Defined '$Name' by $Artist ($Medium) as an illustration"
}
}
Blok kode berikut menunjukkan perilaku kelas turunan Ilustrasi. Ini membuat tiga instans kelas, menunjukkannya dalam tabel, lalu mendaftarkannya dengan metode RegisterWork() statis yang diwariskan. Kemudian memanggil metode statis yang sama pada kelas dasar secara langsung. Terakhir, ia menulis pesan yang menunjukkan daftar artis terdaftar untuk kelas dasar dan kelas turunan.
$Illustrations = @(
[Illustration]@{
Name = 'The Funny Thing'
Artist = 'Wanda Gág'
Medium = 'Lithography'
}
[Illustration]::new('Millions of Cats', 'Wanda Gág')
[Illustration]::new(
'The Lion and the Mouse',
'Jerry Pinkney',
'Watercolor'
)
)
$Illustrations | Format-Table
$Illustrations | ForEach-Object { [Illustration]::RegisterIllustration($_) }
$Illustrations | ForEach-Object { [PublishedWork]::RegisterWork($_) }
"Published work artists: $([PublishedWork]::Artists -join ', ')"
"Illustration artists: $([Illustration]::Artists -join ', ')"
VERBOSE: Defined a published work of type [Illustration]
VERBOSE: Defined an illustration
VERBOSE: Defined 'Millions of Cats' by Wanda Gág as a published work of type [Illustration]
VERBOSE: Defined 'Millions of Cats' by Wanda Gág (Unknown) as an illustration
VERBOSE: Defined a published work of type [Illustration]
VERBOSE: Defined 'The Lion and the Mouse' by Jerry Pinkney (Watercolor) as an illustration
Category Medium Name Artist
-------- ------ ---- ------
Illustrations Lithography The Funny Thing Wanda Gág
Illustrations Unknown Millions of Cats Wanda Gág
Illustrations Watercolor The Lion and the Mouse Jerry Pinkney
VERBOSE: Adding work 'The Funny Thing' to works list
VERBOSE: Adding artist 'Wanda Gág' to artists list
VERBOSE: Adding illustrator 'Wanda Gág' to artists list
VERBOSE: Adding work 'Millions of Cats' to works list
VERBOSE: Artist 'Wanda Gág' already registered.
VERBOSE: Illustrator 'Wanda Gág' already registered.
VERBOSE: Adding work 'The Lion and the Mouse' to works list
VERBOSE: Adding artist 'Jerry Pinkney' to artists list
VERBOSE: Adding illustrator 'Jerry Pinkney' to artists list
VERBOSE: Work 'The Funny Thing' already registered.
VERBOSE: Artist 'Wanda Gág' already registered.
VERBOSE: Work 'Millions of Cats' already registered.
VERBOSE: Artist 'Wanda Gág' already registered.
VERBOSE: Work 'The Lion and the Mouse' already registered.
VERBOSE: Artist 'Jerry Pinkney' already registered.
Published work artists: Pink Floyd, Wu-Tang Clan, Wanda Gág, Jerry Pinkney
Illustration artists: Wanda Gág, Jerry Pinkney
Pesan verbose dari pembuatan instans menunjukkan bahwa:
- Saat membuat instans pertama, konstruktor default kelas dasar dipanggil sebelum konstruktor default kelas turunan.
- Saat membuat instans kedua, konstruktor yang diwariskan secara eksplisit dipanggil untuk kelas dasar sebelum konstruktor kelas turunan.
- Saat membuat instans ketiga, konstruktor default kelas dasar dipanggil sebelum konstruktor kelas turunan.
Pesan verbose dari metode RegisterWork() menunjukkan bahwa karya dan seniman sudah terdaftar. Ini karena metode RegisterIllustration() memanggil metode RegisterWork() secara internal.
Namun, saat membandingkan nilai properti Artis statis untuk kelas dasar dan kelas turunan, nilainya berbeda. Properti Artists untuk kelas turunan hanya mencakup ilustrator, bukan artis album. Mendefinisikan ulang properti Artis di kelas turunan mencegah kelas mengembalikan properti statis pada kelas dasar.
Blok kode akhir memanggil metode ToString() pada entri properti Daftar statis pada kelas dasar.
[PublishedWork]::List | ForEach-Object -Process { $_.ToString() }
The Dark Side of the Moon by Pink Floyd
The Wall by Pink Floyd
36 Chambers by Wu-Tang Clan
The Funny Thing by Wanda Gág (Lithography)
Millions of Cats by Wanda Gág (Unknown)
The Lion and the Mouse by Jerry Pinkney (Watercolor)
Instans-instans Album hanya mengembalikan nama dan artis dalam string mereka. Instans Ilustrasi
Contoh 2 - Menerapkan antarmuka
Contoh berikut menunjukkan bagaimana kelas dapat menerapkan satu atau beberapa antarmuka. Contoh memperluas definisi kelas Suhu untuk mendukung lebih banyak operasi dan perilaku.
Definisi kelas awal
Sebelum menerapkan antarmuka apa pun, kelas Suhu didefinisikan dengan dua properti, Derajat dan Skala. Ini mendefinisikan konstruktor dan tiga metode instans yang mengembalikan instans sebagai nilai pada skala tertentu.
Kelas menentukan skala yang tersedia dengan enumerasi TemperatureScale.
class Temperature {
[float] $Degrees
[TemperatureScale] $Scale
Temperature() {}
Temperature([float] $Degrees) { $this.Degrees = $Degrees }
Temperature([TemperatureScale] $Scale) { $this.Scale = $Scale }
Temperature([float] $Degrees, [TemperatureScale] $Scale) {
$this.Degrees = $Degrees
$this.Scale = $Scale
}
[float] ToKelvin() {
switch ($this.Scale) {
Celsius { return $this.Degrees + 273.15 }
Fahrenheit { return ($this.Degrees + 459.67) * 5/9 }
}
return $this.Degrees
}
[float] ToCelsius() {
switch ($this.Scale) {
Fahrenheit { return ($this.Degrees - 32) * 5/9 }
Kelvin { return $this.Degrees - 273.15 }
}
return $this.Degrees
}
[float] ToFahrenheit() {
switch ($this.Scale) {
Celsius { return $this.Degrees * 9/5 + 32 }
Kelvin { return $this.Degrees * 9/5 - 459.67 }
}
return $this.Degrees
}
}
enum TemperatureScale {
Celsius = 0
Fahrenheit = 1
Kelvin = 2
}
Namun, dalam implementasi dasar ini, ada beberapa batasan seperti yang ditunjukkan dalam contoh output berikut:
$Celsius = [Temperature]::new()
$Fahrenheit = [Temperature]::new([TemperatureScale]::Fahrenheit)
$Kelvin = [Temperature]::new(0, 'Kelvin')
$Celsius, $Fahrenheit, $Kelvin
"The temperatures are: $Celsius, $Fahrenheit, $Kelvin"
[Temperature]::new() -eq $Celsius
$Celsius -gt $Kelvin
Degrees Scale
------- -----
0.00 Celsius
0.00 Fahrenheit
0.00 Kelvin
The temperatures are: Temperature, Temperature, Temperature
False
InvalidOperation:
Line |
11 | $Celsius -gt $Kelvin
| ~~~~~~~~~~~~~~~~~~~~
| Cannot compare "Temperature" because it is not IComparable.
Output menunjukkan bahwa contoh Suhu:
- Tidak ditampilkan dengan benar sebagai string.
- Tidak dapat diperiksa dengan benar untuk kesetaraan.
- Tidak dapat dibandingkan.
Ketiga masalah ini dapat diatasi dengan menerapkan antarmuka untuk kelas .
Menerapkan IFormattable
Antarmuka pertama yang harus diimplementasikan untuk kelas Suhu ToString().
Metode instans ToString() harus memiliki tanda tangan berikut:
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# Implementation
}
Tanda tangan yang diperlukan antarmuka tercantum dalam dokumentasi referensi .
Untuk Temperature, kelas harus mendukung tiga format: C mengembalikan instance dalam Celcius, F untuk mengembalikannya dalam Fahrenheit, dan K untuk mengembalikannya dalam Kelvin. Untuk format lain, metode harus melempar System.FormatException.
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# If format isn't specified, use the defined scale.
if ([string]::IsNullOrEmpty($Format)) {
$Format = switch ($this.Scale) {
Celsius { 'C' }
Fahrenheit { 'F' }
Kelvin { 'K' }
}
}
# If format provider isn't specified, use the current culture.
if ($null -eq $FormatProvider) {
$FormatProvider = [cultureinfo]::CurrentCulture
}
# Format the temperature.
switch ($Format) {
'C' {
return $this.ToCelsius().ToString('F2', $FormatProvider) + '°C'
}
'F' {
return $this.ToFahrenheit().ToString('F2', $FormatProvider) + '°F'
}
'K' {
return $this.ToKelvin().ToString('F2', $FormatProvider) + '°K'
}
}
# If we get here, the format is invalid.
throw [System.FormatException]::new(
"Unknown format: '$Format'. Valid Formats are 'C', 'F', and 'K'"
)
}
Dalam implementasi ini, metode secara default mengacu pada skala instans untuk format dan budaya lokal saat ini saat memformat nilai derajat dalam angka itu sendiri. Ini menggunakan metode instans To<Scale>() untuk mengonversi derajat, memformatnya hingga dua angka desimal, dan menambahkan simbol derajat yang tepat ke dalam string.
Setelah tanda tangan yang diperlukan diimplementasikan, kelas juga dapat mendefinisikan overload untuk mempermudah mengembalikan instans yang sudah diformat.
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
Kode berikut menunjukkan definisi yang diperbarui untuk Suhu:
class Temperature : System.IFormattable {
[float] $Degrees
[TemperatureScale] $Scale
Temperature() {}
Temperature([float] $Degrees) { $this.Degrees = $Degrees }
Temperature([TemperatureScale] $Scale) { $this.Scale = $Scale }
Temperature([float] $Degrees, [TemperatureScale] $Scale) {
$this.Degrees = $Degrees
$this.Scale = $Scale
}
[float] ToKelvin() {
switch ($this.Scale) {
Celsius { return $this.Degrees + 273.15 }
Fahrenheit { return ($this.Degrees + 459.67) * 5 / 9 }
}
return $this.Degrees
}
[float] ToCelsius() {
switch ($this.Scale) {
Fahrenheit { return ($this.Degrees - 32) * 5 / 9 }
Kelvin { return $this.Degrees - 273.15 }
}
return $this.Degrees
}
[float] ToFahrenheit() {
switch ($this.Scale) {
Celsius { return $this.Degrees * 9 / 5 + 32 }
Kelvin { return $this.Degrees * 9 / 5 - 459.67 }
}
return $this.Degrees
}
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# If format isn't specified, use the defined scale.
if ([string]::IsNullOrEmpty($Format)) {
$Format = switch ($this.Scale) {
Celsius { 'C' }
Fahrenheit { 'F' }
Kelvin { 'K' }
}
}
# If format provider isn't specified, use the current culture.
if ($null -eq $FormatProvider) {
$FormatProvider = [cultureinfo]::CurrentCulture
}
# Format the temperature.
switch ($Format) {
'C' {
return $this.ToCelsius().ToString('F2', $FormatProvider) + '°C'
}
'F' {
return $this.ToFahrenheit().ToString('F2', $FormatProvider) + '°F'
}
'K' {
return $this.ToKelvin().ToString('F2', $FormatProvider) + '°K'
}
}
# If we get here, the format is invalid.
throw [System.FormatException]::new(
"Unknown format: '$Format'. Valid Formats are 'C', 'F', and 'K'"
)
}
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
}
enum TemperatureScale {
Celsius = 0
Fahrenheit = 1
Kelvin = 2
}
Output untuk metode kelebihan beban ditunjukkan di blok berikut.
$Temp = [Temperature]::new()
"The temperature is $Temp"
$Temp.ToString()
$Temp.ToString('K')
$Temp.ToString('F', $null)
The temperature is 0.00°C
0.00°C
273.15°K
32.00°F
Menerapkan IEquatable
Sekarang setelah kelas Suhu dapat diformat agar lebih mudah dibaca, pengguna harus dapat memeriksa apakah dua instans kelas tersebut sama. Untuk mendukung pengujian ini, kelas perlu mengimplementasikan antarmuka
Untuk mengimplementasikan antarmuka, kelas perlu mewarisi dari System.IEquatable Equals() harus memiliki tanda tangan berikut:
[bool] Equals([Object]$Other) {
# Implementation
}
Tanda tangan yang diperlukan antarmuka tercantum dalam dokumentasi referensi .
Untuk Temperature, kelas ini hanya boleh mendukung perbandingan antara dua contoh dari kelas tersebut. Untuk nilai atau tipe lainnya, termasuk $null, seharusnya mengembalikan $false. Ketika membandingkan dua suhu, metode harus mengonversi kedua nilai menjadi Kelvin, karena suhu dapat setara bahkan dengan skala yang berbeda.
[bool] Equals([Object]$Other) {
# If the other object is null, we can't compare it.
if ($null -eq $Other) {
return $false
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
return $false
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin() -eq $OtherTemperature.ToKelvin()
}
Definisi yang diperbarui untuk Suhu dengan metode antarmuka yang diterapkan adalah:
class Temperature : System.IFormattable, System.IEquatable[Object] {
[float] $Degrees
[TemperatureScale] $Scale
Temperature() {}
Temperature([float] $Degrees) { $this.Degrees = $Degrees }
Temperature([TemperatureScale] $Scale) { $this.Scale = $Scale }
Temperature([float] $Degrees, [TemperatureScale] $Scale) {
$this.Degrees = $Degrees
$this.Scale = $Scale
}
[float] ToKelvin() {
switch ($this.Scale) {
Celsius { return $this.Degrees + 273.15 }
Fahrenheit { return ($this.Degrees + 459.67) * 5 / 9 }
}
return $this.Degrees
}
[float] ToCelsius() {
switch ($this.Scale) {
Fahrenheit { return ($this.Degrees - 32) * 5 / 9 }
Kelvin { return $this.Degrees - 273.15 }
}
return $this.Degrees
}
[float] ToFahrenheit() {
switch ($this.Scale) {
Celsius { return $this.Degrees * 9 / 5 + 32 }
Kelvin { return $this.Degrees * 9 / 5 - 459.67 }
}
return $this.Degrees
}
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# If format isn't specified, use the defined scale.
if ([string]::IsNullOrEmpty($Format)) {
$Format = switch ($this.Scale) {
Celsius { 'C' }
Fahrenheit { 'F' }
Kelvin { 'K' }
}
}
# If format provider isn't specified, use the current culture.
if ($null -eq $FormatProvider) {
$FormatProvider = [cultureinfo]::CurrentCulture
}
# Format the temperature.
switch ($Format) {
'C' {
return $this.ToCelsius().ToString('F2', $FormatProvider) + '°C'
}
'F' {
return $this.ToFahrenheit().ToString('F2', $FormatProvider) + '°F'
}
'K' {
return $this.ToKelvin().ToString('F2', $FormatProvider) + '°K'
}
}
# If we get here, the format is invalid.
throw [System.FormatException]::new(
"Unknown format: '$Format'. Valid Formats are 'C', 'F', and 'K'"
)
}
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
[bool] Equals([Object]$Other) {
# If the other object is null, we can't compare it.
if ($null -eq $Other) {
return $false
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
return $false
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin() -eq $OtherTemperature.ToKelvin()
}
}
enum TemperatureScale {
Celsius = 0
Fahrenheit = 1
Kelvin = 2
}
Blok berikut menunjukkan perilaku kelas yang diperbarui:
$Celsius = [Temperature]::new()
$Fahrenheit = [Temperature]::new(32, 'Fahrenheit')
$Kelvin = [Temperature]::new([TemperatureScale]::Kelvin)
@"
Temperatures are: $Celsius, $Fahrenheit, $Kelvin
`$Celsius.Equals(`$Fahrenheit) = $($Celsius.Equals($Fahrenheit))
`$Celsius -eq `$Fahrenheit = $($Celsius -eq $Fahrenheit)
`$Celsius -ne `$Kelvin = $($Celsius -ne $Kelvin)
"@
Temperatures are: 0.00°C, 32.00°F, 0.00°K
$Celsius.Equals($Fahrenheit) = True
$Celsius -eq $Fahrenheit = True
$Celsius -ne $Kelvin = True
Menerapkan IComparable
Antarmuka terakhir untuk diimplementasikan untuk kelas Suhu adalah System.IComparable. Ketika kelas menerapkan antarmuka ini, pengguna dapat menggunakan operator -lt, -le, -gt, dan -ge untuk membandingkan instans kelas.
Untuk mengimplementasikan antarmuka, kelas perlu mewarisi dari System.IComparable Equals() harus memiliki tanda tangan berikut:
[int] CompareTo([Object]$Other) {
# Implementation
}
Tanda tangan yang diperlukan antarmuka tercantum dalam dokumentasi referensi .
Untuk Temperature, kelas ini hanya boleh mendukung perbandingan antara dua contoh dari kelas tersebut. Karena tipe dasar dari properti Degrees, bahkan ketika dikonversi ke skala yang berbeda, adalah bilangan titik mengambang, metode ini dapat mengandalkan tipe dasar tersebut untuk melakukan perbandingan yang sebenarnya.
[int] CompareTo([Object]$Other) {
# If the other object's null, consider this instance "greater than" it
if ($null -eq $Other) {
return 1
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
throw [System.ArgumentException]::new(
"Object must be of type 'Temperature'."
)
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin().CompareTo($OtherTemperature.ToKelvin())
}
Definisi akhir untuk kelas Suhu adalah:
class Temperature : System.IFormattable,
System.IComparable,
System.IEquatable[Object] {
# Instance properties
[float] $Degrees
[TemperatureScale] $Scale
# Constructors
Temperature() {}
Temperature([float] $Degrees) { $this.Degrees = $Degrees }
Temperature([TemperatureScale] $Scale) { $this.Scale = $Scale }
Temperature([float] $Degrees, [TemperatureScale] $Scale) {
$this.Degrees = $Degrees
$this.Scale = $Scale
}
[float] ToKelvin() {
switch ($this.Scale) {
Celsius { return $this.Degrees + 273.15 }
Fahrenheit { return ($this.Degrees + 459.67) * 5 / 9 }
}
return $this.Degrees
}
[float] ToCelsius() {
switch ($this.Scale) {
Fahrenheit { return ($this.Degrees - 32) * 5 / 9 }
Kelvin { return $this.Degrees - 273.15 }
}
return $this.Degrees
}
[float] ToFahrenheit() {
switch ($this.Scale) {
Celsius { return $this.Degrees * 9 / 5 + 32 }
Kelvin { return $this.Degrees * 9 / 5 - 459.67 }
}
return $this.Degrees
}
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# If format isn't specified, use the defined scale.
if ([string]::IsNullOrEmpty($Format)) {
$Format = switch ($this.Scale) {
Celsius { 'C' }
Fahrenheit { 'F' }
Kelvin { 'K' }
}
}
# If format provider isn't specified, use the current culture.
if ($null -eq $FormatProvider) {
$FormatProvider = [cultureinfo]::CurrentCulture
}
# Format the temperature.
switch ($Format) {
'C' {
return $this.ToCelsius().ToString('F2', $FormatProvider) + '°C'
}
'F' {
return $this.ToFahrenheit().ToString('F2', $FormatProvider) + '°F'
}
'K' {
return $this.ToKelvin().ToString('F2', $FormatProvider) + '°K'
}
}
# If we get here, the format is invalid.
throw [System.FormatException]::new(
"Unknown format: '$Format'. Valid Formats are 'C', 'F', and 'K'"
)
}
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
[bool] Equals([Object]$Other) {
# If the other object is null, we can't compare it.
if ($null -eq $Other) {
return $false
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
return $false
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin() -eq $OtherTemperature.ToKelvin()
}
[int] CompareTo([Object]$Other) {
# If the other object's null, consider this instance "greater than" it
if ($null -eq $Other) {
return 1
}
# If the other object isn't a temperature, we can't compare it.
$OtherTemperature = $Other -as [Temperature]
if ($null -eq $OtherTemperature) {
throw [System.ArgumentException]::new(
"Object must be of type 'Temperature'."
)
}
# Compare the temperatures as Kelvin.
return $this.ToKelvin().CompareTo($OtherTemperature.ToKelvin())
}
}
enum TemperatureScale {
Celsius = 0
Fahrenheit = 1
Kelvin = 2
}
Dengan definisi lengkap, pengguna dapat memformat dan membandingkan instans kelas di PowerShell seperti jenis bawaan apa pun.
$Celsius = [Temperature]::new()
$Fahrenheit = [Temperature]::new(32, 'Fahrenheit')
$Kelvin = [Temperature]::new([TemperatureScale]::Kelvin)
@"
Temperatures are: $Celsius, $Fahrenheit, $Kelvin
`$Celsius.Equals(`$Fahrenheit) = $($Celsius.Equals($Fahrenheit))
`$Celsius.Equals(`$Kelvin) = $($Celsius.Equals($Kelvin))
`$Celsius.CompareTo(`$Fahrenheit) = $($Celsius.CompareTo($Fahrenheit))
`$Celsius.CompareTo(`$Kelvin) = $($Celsius.CompareTo($Kelvin))
`$Celsius -lt `$Fahrenheit = $($Celsius -lt $Fahrenheit)
`$Celsius -le `$Fahrenheit = $($Celsius -le $Fahrenheit)
`$Celsius -eq `$Fahrenheit = $($Celsius -eq $Fahrenheit)
`$Celsius -gt `$Kelvin = $($Celsius -gt $Kelvin)
"@
Temperatures are: 0.00°C, 32.00°F, 0.00°K
$Celsius.Equals($Fahrenheit) = True
$Celsius.Equals($Kelvin) = False
$Celsius.CompareTo($Fahrenheit) = 0
$Celsius.CompareTo($Kelvin) = 1
$Celsius -lt $Fahrenheit = False
$Celsius -le $Fahrenheit = True
$Celsius -eq $Fahrenheit = True
$Celsius -gt $Kelvin = True
Contoh 3 - Mewarisi dari kelas dasar generik
Contoh ini menunjukkan bagaimana Anda dapat memperoleh dari jenis generik selama parameter jenis sudah ditentukan pada waktu penguraian.
Menggunakan kelas bawaan sebagai parameter jenis
Jalankan blok kode berikut. Ini menunjukkan bagaimana kelas baru dapat mewarisi dari jenis generik selama parameter jenis sudah ditentukan pada waktu penguraian.
class ExampleStringList : System.Collections.Generic.List[string] {}
$List = [ExampleStringList]::new()
$List.AddRange([string[]]@('a','b','c'))
$List.GetType() | Format-List -Property Name, BaseType
$List
Name : ExampleStringList
BaseType : System.Collections.Generic.List`1[System.String]
a
b
c
Menggunakan kelas kustom sebagai parameter jenis
Blok kode berikutnya pertama-tama mendefinisikan kelas baru, ExampleItem, dengan satu properti instans dan metode ToString(). Kemudian mendefinisikan kelas
Salin seluruh blok kode dan jalankan sebagai satu pernyataan.
class ExampleItem {
[string] $Name
[string] ToString() { return $this.Name }
}
class ExampleItemList : System.Collections.Generic.List[ExampleItem] {}
ParentContainsErrorRecordException: An error occurred while creating the pipeline.
Menjalankan seluruh blok kode menimbulkan kesalahan karena PowerShell belum memuat kelas
Jalankan blok kode berikut dalam urutan yang ditentukan.
class ExampleItem {
[string] $Name
[string] ToString() { return $this.Name }
}
class ExampleItemList : System.Collections.Generic.List[ExampleItem] {}
Kali ini, PowerShell tidak menimbulkan kesalahan apa pun. Kedua kelas kini sudah terdefinisi. Jalankan blok kode berikut untuk melihat perilaku kelas baru.
$List = [ExampleItemList]::new()
$List.AddRange([ExampleItem[]]@(
[ExampleItem]@{ Name = 'Foo' }
[ExampleItem]@{ Name = 'Bar' }
[ExampleItem]@{ Name = 'Baz' }
))
$List.GetType() | Format-List -Property Name, BaseType
$List
Name : ExampleItemList
BaseType : System.Collections.Generic.List`1[ExampleItem]
Name
----
Foo
Bar
Baz
Mendefinisikan generik dengan parameter tipe kustom dalam modul
Blok kode berikut menunjukkan bagaimana Anda dapat menentukan kelas yang mewarisi dari kelas dasar generik yang menggunakan jenis kustom untuk parameter jenis.
Simpan blok kode berikut sebagai GenericExample.psd1.
@{
RootModule = 'GenericExample.psm1'
ModuleVersion = '0.1.0'
GUID = '2779fa60-0b3b-4236-b592-9060c0661ac2'
}
Simpan blok kode berikut sebagai GenericExample.InventoryItem.psm1.
class InventoryItem {
[string] $Name
[int] $Count
InventoryItem() {}
InventoryItem([string]$Name) {
$this.Name = $Name
}
InventoryItem([string]$Name, [int]$Count) {
$this.Name = $Name
$this.Count = $Count
}
[string] ToString() {
return "$($this.Name) ($($this.Count))"
}
}
Simpan blok kode berikut sebagai GenericExample.psm1.
using namespace System.Collections.Generic
using module ./GenericExample.InventoryItem.psm1
class Inventory : List[InventoryItem] {}
# Define the types to export with type accelerators.
$ExportableTypes =@(
[InventoryItem]
[Inventory]
)
# 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()
Saran
Modul inti menambahkan tipe kustom ke akselerator tipe PowerShell. Pola ini memungkinkan pengguna modul untuk segera mengakses IntelliSense dan pelengkapan otomatis untuk jenis kustom tanpa perlu menggunakan pernyataan using module terlebih dahulu.
Untuk informasi lebih lanjut tentang pola ini, lihat bagian "Mengekspor dengan akselerator jenis" dari about_Classes.
Impor modul dan verifikasi output.
Import-Module ./GenericExample.psd1
$Inventory = [Inventory]::new()
$Inventory.GetType() | Format-List -Property Name, BaseType
$Inventory.Add([InventoryItem]::new('Bucket', 2))
$Inventory.Add([InventoryItem]::new('Mop'))
$Inventory.Add([InventoryItem]@{ Name = 'Broom' ; Count = 4 })
$Inventory
Name : Inventory
BaseType : System.Collections.Generic.List`1[InventoryItem]
Name Count
---- -----
Bucket 2
Mop 0
Broom 4
Modul dimuat tanpa kesalahan karena kelas InventoryItem didefinisikan dalam file modul yang berbeda dari kelas Inventory. Kedua kelas tersedia untuk pengguna modul.
Mewarisi kelas dasar
Ketika kelas mewarisi dari kelas dasar, kelas tersebut mewarisi properti dan metode kelas dasar. Ini tidak mewarisi konstruktor kelas dasar secara langsung, tetapi dapat memanggilnya.
Saat kelas dasar didefinisikan dalam .NET daripada PowerShell, perhatikan bahwa:
- Kelas PowerShell tidak dapat mewarisi dari kelas yang tertutup.
- Saat mewarisi dari kelas dasar generik, parameter jenis untuk kelas generik tidak dapat menjadi kelas turunan. Menggunakan kelas turunan sebagai parameter tipe menimbulkan kesalahan penguraian.
Untuk melihat cara kerja pewarisan dan overriding untuk kelas turunan, lihat Contoh 1.
Konstruktor kelas turunan
Kelas turunan tidak secara langsung mewarisi konstruktor kelas dasar. Jika kelas dasar mendefinisikan konstruktor default dan kelas turunan tidak menentukan konstruktor apa pun, instans baru kelas turunan menggunakan konstruktor default kelas dasar. Jika kelas dasar tidak menentukan konstruktor default, kelas turunan harus secara eksplisit menentukan setidaknya satu konstruktor.
Konstruktor kelas turunan dapat memanggil konstruktor dari kelas dasar dengan kata kunci base. Jika kelas turunan tidak secara eksplisit memanggil konstruktor dari kelas dasar, itu memanggil konstruktor default untuk kelas dasar sebagai gantinya.
Untuk memanggil konstruktor dasar nondefault, tambahkan : base(<parameters>) setelah parameter konstruktor dan sebelum blok isi.
class <derived-class> : <base-class> {
<derived-class>(<derived-parameters>) : <base-class>(<base-parameters>) {
# initialization code
}
}
Saat menentukan konstruktor yang memanggil konstruktor kelas dasar, parameter dapat menjadi salah satu item berikut:
- Variabel parameter apa pun pada konstruktor kelas turunan.
- Nilai statis apa pun.
- Ekspresi apa pun yang mengevaluasi ke nilai jenis parameter.
Ilustrasi kelas di Contoh 1 menunjukkan bagaimana kelas turunan dapat menggunakan konstruktor kelas dasar.
Metode kelas turunan
Ketika kelas berasal dari kelas dasar, kelas tersebut mewarisi metode kelas dasar dan kelebihan bebannya. Setiap metode kelebihan beban yang ditentukan pada kelas dasar, termasuk metode tersembunyi, tersedia pada kelas turunan.
Kelas turunan dapat mengambil alih kelebihan metode yang diwariskan dengan mendefinisikannya kembali dalam definisi kelas. Untuk mengambil alih kelebihan beban, jenis parameter harus sama dengan untuk kelas dasar. Jenis output untuk kelebihan beban bisa berbeda.
Tidak seperti konstruktor, metode tidak dapat menggunakan sintaks : base(<parameters>) untuk memanggil kelebihan beban kelas dasar untuk metode . Kelebihan beban yang ditentukan ulang pada kelas turunan sepenuhnya menggantikan kelebihan beban yang ditentukan oleh kelas dasar. Untuk memanggil metode kelas dasar untuk instans, transmisikan variabel instans ($this) ke kelas dasar sebelum memanggil metode .
Cuplikan berikut menunjukkan bagaimana kelas turunan dapat memanggil metode kelas dasar.
class BaseClass {
[bool] IsTrue() { return $true }
}
class DerivedClass : BaseClass {
[bool] IsTrue() { return $false }
[bool] BaseIsTrue() { return ([BaseClass]$this).IsTrue() }
}
@"
[BaseClass]::new().IsTrue() = $([BaseClass]::new().IsTrue())
[DerivedClass]::new().IsTrue() = $([DerivedClass]::new().IsTrue())
[DerivedClass]::new().BaseIsTrue() = $([DerivedClass]::new().BaseIsTrue())
"@
[BaseClass]::new().IsTrue() = True
[DerivedClass]::new().IsTrue() = False
[DerivedClass]::new().BaseIsTrue() = True
Untuk sampel yang diperluas yang menunjukkan bagaimana kelas turunan dapat mengambil alih metode yang diwariskan, lihat kelas Ilustrasi
Properti kelas turunan
Ketika kelas berasal dari kelas dasar, kelas tersebut mewarisi properti kelas dasar. Properti apa pun yang ditentukan pada kelas dasar, termasuk properti tersembunyi, tersedia di kelas turunan.
Kelas turunan dapat mengambil alih properti yang diwariskan dengan mendefinisikannya kembali dalam definisi kelas. Properti pada kelas turunan menggunakan jenis yang ditentukan ulang dan nilai default, jika ada. Jika properti yang diwariskan menentukan nilai default dan properti yang ditentukan ulang tidak, properti yang diwariskan tidak memiliki nilai default.
Jika kelas turunan tidak mengambil alih properti statis, mengakses properti statis melalui kelas turunan mengakses properti statis kelas dasar. Memodifikasi nilai properti melalui kelas turunan memodifikasi nilai pada kelas dasar. Kelas turunan lainnya yang tidak mengambil alih properti statis juga menggunakan nilai properti pada kelas dasar. Memperbarui nilai properti statis yang diwariskan di kelas yang tidak menggantikan properti tersebut mungkin memiliki efek yang tidak diinginkan pada kelas turunan dari kelas dasar yang sama.
Contoh 1 menunjukkan bagaimana kelas turunan yang mewarisi, memperluas, dan mengambil alih properti kelas dasar.
Berasal dari konsep generik
Ketika kelas berasal dari generik, parameter jenis harus sudah ditentukan sebelum PowerShell mengurai kelas turunan. Jika parameter jenis untuk generik adalah kelas PowerShell atau enumerasi yang ditentukan dalam file atau blok kode yang sama, PowerShell menimbulkan kesalahan.
Untuk mendapatkan kelas dari kelas dasar generik dengan jenis kustom sebagai parameter jenis, tentukan kelas atau enumerasi untuk parameter jenis dalam file atau modul yang berbeda dan gunakan pernyataan using module untuk memuat definisi jenis.
Untuk contoh yang menunjukkan cara mewarisi dari kelas dasar generik, lihat Contoh 3.
Kelas yang berguna untuk diwarisi
Ada beberapa kelas yang dapat berguna untuk diwarisi saat menulis modul PowerShell. Bagian ini mencantumkan beberapa kelas dasar dan menjelaskan untuk apa kelas yang diturunkan dari kelas tersebut dapat digunakan.
- System.Attribute - Memperoleh kelas untuk menentukan atribut yang dapat digunakan untuk variabel, parameter, definisi kelas dan enumerasi, dan banyak lagi.
- System.Management.Automation.ArgumentTransformationAttribute - Mendapatkan kelas untuk menangani konversi input untuk variabel atau parameter ke dalam jenis data tertentu.
- System.Management.Automation.ValidateArgumentsAttribute - Mendapatkan kelas untuk menerapkan validasi kustom ke variabel, parameter, dan properti kelas.
- System.Collections.Generic.List - Mendapatkan kelas untuk membuat dan mengelola daftar tipe data tertentu lebih mudah.
- System.Exception - Memperoleh kelas untuk menentukan kesalahan kustom.
Menerapkan antarmuka
Kelas PowerShell yang mengimplementasikan antarmuka harus mengimplementasikan semua anggota antarmuka tersebut. Menghilangkan anggota antarmuka implementasi menyebabkan kesalahan waktu parsing dalam skrip.
Nota
PowerShell tidak mendukung deklarasikan antarmuka baru dalam skrip PowerShell.
Sebagai gantinya, antarmuka harus dideklarasikan dalam kode .NET dan ditambahkan ke sesi dengan cmdlet Add-Type atau pernyataan using assembly.
Ketika kelas mengimplementasikan antarmuka, itu dapat digunakan seperti kelas lain yang mengimplementasikan antarmuka tersebut. Beberapa perintah dan operasi membatasi jenis yang didukung ke kelas yang mengimplementasikan antarmuka tertentu.
Untuk meninjau contoh implementasi antarmuka, lihat Contoh 2.
Antarmuka yang berguna untuk diimplementasikan
Ada beberapa kelas antarmuka yang dapat berguna untuk mewarisi saat menulis modul PowerShell. Bagian ini mencantumkan beberapa kelas dasar dan menjelaskan untuk apa kelas yang diturunkan dari kelas tersebut dapat digunakan.
- System.IEquatable - Antarmuka ini memungkinkan pengguna untuk membandingkan dua instans kelas. Saat kelas tidak menerapkan antarmuka ini, PowerShell memeriksa kesetaraan antara dua instans menggunakan kesetaraan referensi. Dengan kata lain, instans kelas hanya sama dengan dirinya sendiri, bahkan jika nilai properti pada dua instans sama.
-
System.IComparable - Antarmuka ini memungkinkan pengguna membandingkan instans kelas dengan operator perbandingan
-le,-lt,-ge, dan-gt. Ketika kelas tidak menerapkan antarmuka ini, operator tersebut menimbulkan kesalahan. - System.IFormattable - Antarmuka ini memungkinkan pengguna memformat instans kelas ke dalam string yang berbeda. Ini berguna untuk kelas yang memiliki lebih dari satu representasi string standar, seperti item anggaran, bibliografi, dan suhu.
- System.IConvertible - Antarmuka ini memungkinkan pengguna untuk mengonversi instans kelas ke jenis runtime lainnya. Ini berguna untuk kelas yang memiliki nilai numerik yang mendasar atau dapat dikonversi menjadi satu.
Keterbatasan
PowerShell tidak mendukung pendefinisian antarmuka dalam kode skrip.
Solusi sementara: Tentukan antarmuka di C# dan referensikan rakitan yang menentukan antarmuka.
Kelas PowerShell hanya dapat mewarisi dari satu kelas dasar.
Solusi sementara: Pewarisan kelas bersifat transitif. Kelas turunan dapat mewarisi dari kelas turunan lain untuk mendapatkan properti dan metode kelas dasar.
Saat mewarisi dari kelas atau antarmuka generik, parameter jenis untuk generik harus sudah ditentukan. Kelas tidak dapat mendefinisikan dirinya sebagai parameter jenis untuk kelas atau antarmuka.
Solusi sementara: Untuk memperoleh dari kelas atau antarmuka dasar generik, tentukan jenis kustom dalam file
.psm1yang berbeda dan gunakan pernyataanusing moduleuntuk memuat jenis. Tidak ada solusi bagi jenis kustom untuk menggunakan dirinya sendiri sebagai parameter tipe saat mewarisi dari generik.