Sınıfların Mirası hakkında
Kısa açıklama
Diğer türleri genişleten sınıfları nasıl tanımlayabileceğinizi açıklar.
Uzun açıklama
PowerShell sınıfları, bir üst sınıfın davranışını yeniden kullanan (devralan), genişleten veya değiştiren bir alt sınıf tanımlamanıza olanak tanıyan kalıtım'ı destekler. Üyeleri miras alınan sınıfa temel sınıf adı verilir. Temel sınıfın üyelerini miras alan sınıfa türetilmiş sınıf adı verilir.
PowerShell yalnızca tekli devralmayı destekler. Bir sınıf yalnızca tek bir sınıftan miras alabilir. Ancak miras geçişlidir ve bu, bir dizi tür için bir miras hiyerarşisi tanımlamanıza olanak tanır. Başka bir deyişle, D türü C türünden miras alabilir, bu tür B türünden miras alabilir ve A temel sınıf türünden miras alabilir . Kalıtım geçişli olduğundan, A türündeki üyeler D türünde kullanılabilir.
Türetilmiş sınıflar temel sınıfın tüm üyelerini miras almaz. Aşağıdaki üyeler devralınmaz:
- Bir sınıfın statik verilerini başlatan statik yapıcılar.
- Sınıfın yeni bir örneğini oluşturmak için çağırdığınız örnek oluşturucular. Her sınıf kendi yapıcılarını tanımlamalıdır.
Mevcut bir sınıftan türetilen yeni bir sınıf oluşturarak bir sınıfı genişletebilirsiniz. Türetilmiş sınıf, temel sınıfın özelliklerini ve yöntemlerini miras alır. Temel sınıf üyelerini gerektiği gibi ekleyebilir veya geçersiz kılabilirsiniz.
Sınıflar ayrıca bir sözleşmeyi tanımlayan arayüzlerden de miras alabilir. Bir arayüzden miras alan bir sınıfın bu sözleşmeyi uygulaması gerekir. Bunu yaptığında sınıf, bu arayüzü uygulayan diğer sınıflar gibi kullanılabilir. Bir sınıf bir arayüzden miras alır ancak arayüzü uygulamazsa PowerShell sınıf için bir ayrıştırma hatası oluşturur.
Bazı PowerShell operatörleri, belirli bir arayüzü uygulayan bir sınıfa bağlıdır. Örneğin, -eq operatörü, sınıf System.IEquatable arayüzünü uygulamadığı sürece yalnızca referans eşitliğini kontrol eder. -le, -lt, -ge ve -gt operatörleri yalnızca <'yi uygulayan sınıflarda çalışır.System.IComparable arayüzü.
Türetilmiş bir sınıf, bir temel sınıfı genişletmek veya arayüzleri uygulamak için : sözdizimini kullanır. Türetilmiş sınıf her zaman sınıf bildiriminde en solda olmalıdır.
Bu örnek, temel PowerShell sınıfı devralma sözdizimini gösterir.
Class Derived : Base {...}
Bu örnekte, temel sınıftan sonra gelen bir arayüz bildirimiyle kalıtım gösterilmektedir.
Class Derived : Base, Interface {...}
Sözdizimi
Sınıf mirası aşağıdaki sözdizimlerini kullanır:
Tek satır sözdizimi
class <derived-class-name> : <base-class-or-interface-name>[, <interface-name>...] {
<derived-class-body>
}
Örneğin:
# Base class only
class Derived : Base {...}
# Interface only
class Derived : System.IComparable {...}
# Base class and interface
class Derived : Base, System.IComparable {...}
Çok satırlı sözdizimi
class <derived-class-name> : <base-class-or-interface-name>[,
<interface-name>...] {
<derived-class-body>
}
Örneğin:
class Derived : Base,
System.IComparable,
System.IFormattable,
System.IConvertible {
# Derived class definition
}
Örnekler
Örnek 1 - Temel sınıftan miras alma ve geçersiz kılma
Aşağıdaki örnek, devralınan özelliklerin geçersiz kılma ile ve geçersiz kılma olmadan davranışını gösterir. Açıklamalarını okuduktan sonra kod bloklarını sırasıyla çalıştırın.
Temel sınıfı tanımlama
İlk kod bloğu PublishedWork'u temel sınıf olarak tanımlar. İki statik özelliği vardır: Liste ve Sanatçılar. Daha sonra, statik List özelliğine eserleri ve Artists özelliğine sanatçıları eklemek için statik RegisterWork() yöntemini tanımlar ve bir mesaj yazar. Listelerdeki her yeni giriş için.
Sınıf, yayınlanmış bir çalışmayı tanımlayan üç örnek özelliği tanımlar. Son olarak Register() ve ToString() örnek yöntemlerini tanımlar.
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)" }
}
Geçersiz kılmalar olmadan türetilmiş bir sınıf tanımlama
Türetilen ilk sınıf Album'dur. Hiçbir özelliği veya yöntemi geçersiz kılmaz. Temel sınıfta bulunmayan yeni bir örnek özelliği olan Genres'i ekler.
class Album : PublishedWork {
[string[]] $Genres = @()
}
Aşağıdaki kod bloğu, türetilmiş Album sınıfının davranışını gösterir. İlk olarak $VerbosePreference değerini ayarlar, böylece sınıf yöntemlerinden gelen mesajlar konsola gönderilir. Sınıfın üç örneğini oluşturur, bunları bir tabloda gösterir ve ardından devralınan statik RegisterWork() yöntemiyle kaydeder. Daha sonra aynı statik yöntemi doğrudan temel sınıfta çağırır.
$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.
Album sınıfının Category veya herhangi bir oluşturucu için bir değer tanımlamamasına rağmen özelliğin temel sınıfın varsayılan oluşturucusu tarafından tanımlandığına dikkat edin.
Ayrıntılı mesajlaşmada RegisterWork() yöntemine yapılan ikinci çağrı, eserlerin ve sanatçıların zaten kayıtlı olduğunu bildiriyor. RegisterWork()'a ilk çağrı türetilmiş Album sınıfı için yapılmış olsa da, temel PublishedWork sınıfından devralınan statik yöntemi kullandı. Bu yöntem, temel sınıftaki statik List ve Artist özelliklerini güncelledi ve türetilmiş sınıf bunları geçersiz kılmadı.
Sonraki kod bloğu kayıt defterini temizler ve Album nesnelerinde Register() örnek yöntemini çağırır.
[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
Album nesnelerindeki örnek yöntemi, türetilmiş veya temel sınıfta statik yöntemin çağrılmasıyla aynı etkiye sahiptir.
Aşağıdaki kod bloğu, temel sınıfın ve türetilmiş sınıfın statik özelliklerini karşılaştırarak bunların aynı olduğunu gösterir.
[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
Geçersiz kılmalarla türetilmiş bir sınıf tanımlama
Sonraki kod bloğu, temel PublishedWork sınıfından devralınan Illustration sınıfını tanımlar. Yeni sınıf, Medium örnek özelliğini varsayılan Bilinmeyen değeriyle tanımlayarak temel sınıfı genişletir.
Türetilmiş Album sınıfından farklı olarak Illustration aşağıdaki özellikleri ve yöntemleri geçersiz kılar:
- Statik Sanatçılar özelliğini geçersiz kılar. Tanım aynıdır ancak Illustration sınıfı bunu doğrudan bildirir.
- Varsayılan değeri
Illustrationsolarak ayarlayarak Category örnek özelliğini geçersiz kılar. ToString()örnek yöntemini geçersiz kılar, böylece bir illüstrasyonun dize temsili, birlikte oluşturulduğu ortamı içerir.
Sınıf ayrıca, önce temel sınıf RegisterWork() yöntemini çağırmak ve ardından sanatçıyı geçersiz kılınan Sanatçılar'a eklemek için statik RegisterIllustration() yöntemini de tanımlar. türetilmiş sınıftaki statik özellik.
Son olarak sınıf, üç kurucunun tümünü geçersiz kılar:
- Varsayılan kurucu, bir illüstrasyon oluşturduğunu belirten ayrıntılı bir mesaj dışında boştur.
- Sonraki yapıcı, illüstrasyonu oluşturan isim ve sanatçı için iki dize değeri alır. Yapıcı, Ad ve Sanatçı özelliklerini ayarlama mantığını uygulamak yerine temel sınıftan uygun kurucuyu çağırır.
- Son yapıcı, illüstrasyonun adı, sanatçısı ve ortamı için üç dize değeri alır. Her iki kurucu da bir illüstrasyon oluşturduklarını belirten ayrıntılı bir mesaj yazar.
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"
}
}
Aşağıdaki kod bloğu, türetilmiş Illustration sınıfının davranışını gösterir. Sınıfın üç örneğini oluşturur, bunları bir tabloda gösterir ve ardından devralınan statik RegisterWork() yöntemiyle kaydeder. Daha sonra aynı statik yöntemi doğrudan temel sınıfta çağırır. Son olarak temel sınıf ve türetilmiş sınıf için kayıtlı sanatçıların listesini gösteren mesajlar yazar.
$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
Örneklerin oluşturulmasından elde edilen ayrıntılı mesajlar şunları gösterir:
- İlk örneği oluştururken, temel sınıf varsayılan yapıcısı, türetilmiş sınıf varsayılan yapıcısından önce çağrıldı.
- İkinci örneği oluştururken, temel sınıf için açıkça miras alınan kurucu, türetilmiş sınıf kurucusundan önce çağrıldı.
- Üçüncü örneği oluştururken, temel sınıfın varsayılan kurucusu, türetilmiş sınıf kurucusundan önce çağrıldı.
RegisterWork() yönteminden gelen ayrıntılı mesajlar, eserlerin ve sanatçıların zaten kayıtlı olduğunu gösterir. Bunun nedeni, RegisterIllustration() yönteminin dahili olarak RegisterWork() yöntemini çağırmasıdır.
Ancak hem temel sınıf hem de türetilmiş sınıf için statik Artist özelliğinin değeri karşılaştırılırken değerler farklıdır. Türetilmiş sınıfın Artists özelliği, albüm sanatçılarını değil, yalnızca illüstratörleri içerir. Türetilmiş sınıfta Artist özelliğinin yeniden tanımlanması, sınıfın temel sınıfta statik özelliği döndürmesini engeller.
Son kod bloğu, temel sınıftaki statik List özelliğinin girişlerinde ToString() yöntemini çağırır.
[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)
Albüm örnekleri yalnızca dizelerindeki adı ve sanatçıyı döndürür. Illustration örnekleri ayrıca ortamı parantez içinde içeriyordu çünkü bu sınıf ToString() yöntemini geçersiz kıldı.
Örnek 2 - Arayüzlerin uygulanması
Aşağıdaki örnek, bir sınıfın bir veya daha fazla arayüzü nasıl uygulayabileceğini gösterir. Örnek, daha fazla işlem ve davranışı desteklemek için Temperature sınıfının tanımını genişletmektedir.
İlk sınıf tanımı
Herhangi bir arayüzü uygulamadan önce, Temperature sınıfı iki özellikle tanımlanır: Degrees ve Scale. Örneği belirli bir ölçeğin dereceleri olarak döndürmek için yapıcıları ve üç örnek yöntemini tanımlar.
Sınıf, kullanılabilir ölçekleri TemperatureScale numaralandırmasıyla tanımlar.
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
}
Ancak bu temel uygulamada aşağıdaki örnek çıktıda gösterildiği gibi birkaç sınırlama vardır:
$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.
Çıktı, Sıcaklık örneklerini gösterir:
- Dize olarak doğru şekilde görüntülenmiyor.
- Eşdeğerlik açısından düzgün bir şekilde kontrol edilemiyor.
- Karşılaştırılamaz.
Bu üç sorun, sınıfa yönelik arayüzlerin uygulanmasıyla çözülebilir.
IFormattable'ı Uygulamak
Temperature sınıfı için uygulanacak ilk arayüz System.IFormattable'dır. Bu arayüz, sınıfın bir örneğinin farklı dizeler olarak biçimlendirilmesini sağlar. Arayüzü uygulamak için sınıfın System.IFormattable'dan miras alması ve ToString() örnek yöntemini tanımlaması gerekir.
ToString() örnek yönteminin aşağıdaki imzaya sahip olması gerekir:
[string] ToString(
[string]$Format,
[System.IFormatProvider]$FormatProvider
) {
# Implementation
}
Arayüzün gerektirdiği imza, referans belgelerde listelenmiştir.
Sıcaklık için sınıfın üç biçimi desteklemesi gerekir: örneği Celsius cinsinden döndürmek için C, Fahrenheit cinsinden döndürmek için F ve Kelvin cinsinden döndürmek için K. Diğer formatlar için yöntemin bir System.FormatException oluşturması gerekir.
[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'"
)
}
Bu uygulamada, sayısal derece değerinin kendisini formatlarken, yöntem varsayılan olarak format için örnek ölçeğini ve mevcut kültürü kullanır. Dereceleri dönüştürmek için To örnek yöntemlerini kullanır, bunları iki ondalık basamaklara göre biçimlendirir ve uygun derece sembolünü dizeye ekler.
Gerekli imzanın uygulanmasıyla sınıf, biçimlendirilmiş örneğin döndürülmesini kolaylaştırmak için aşırı yüklemeleri de tanımlayabilir.
[string] ToString([string]$Format) {
return $this.ToString($Format, $null)
}
[string] ToString() {
return $this.ToString($null, $null)
}
Aşağıdaki kod, Sıcaklık'ın güncellenmiş tanımını gösterir:
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
}
Yöntem aşırı yüklemelerinin çıkışı aşağıdaki blokta gösterilmektedir.
$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
IEquatable'ı Uygulamak
Artık Temperature sınıfı okunabilirlik için biçimlendirilebildiğine göre, kullanıcıların sınıfın iki örneğinin eşit olup olmadığını kontrol edebilmesi gerekiyor. Bu testi desteklemek için sınıfın System.IEquatable arayüzünü uygulaması gerekir.
Arayüzü uygulamak için sınıfın System.IEquatable'dan miras alması ve Equals() örnek yöntemini tanımlaması gerekir. Equals() yönteminin aşağıdaki imzaya sahip olması gerekir:
[bool] Equals([object]$Other) {
# Implementation
}
Arayüzün gerektirdiği imza, referans belgelerde listelenmiştir.
Sıcaklık için sınıf yalnızca sınıfın iki örneğinin karşılaştırılmasını desteklemelidir. $null dahil olmak üzere diğer herhangi bir değer veya tür için $false döndürmelidir. İki sıcaklığı karşılaştırırken, sıcaklıklar farklı ölçeklerde bile eşdeğer olabileceğinden, yöntemin her iki değeri de Kelvin'e dönüştürmesi gerekir.
[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()
}
Uygulanan arayüz yöntemiyle Sıcaklık'ın güncellenmiş tanımı şöyledir:
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
}
Aşağıdaki blok güncellenen sınıfın nasıl davrandığını gösterir:
$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
IComparable'ı Uygulamak
Temperature sınıfı için uygulanacak son arayüz System.IComparable'dur. Sınıf bu arayüzü uyguladığında kullanıcılar -lt, -le, -gt ve -ge'yi kullanabilirler > sınıfın örneklerini karşılaştırmak için operatörler.
Arayüzü uygulamak için sınıfın System.IComparable'dan miras alması ve Equals() örnek yöntemini tanımlaması gerekir. Equals() yönteminin aşağıdaki imzaya sahip olması gerekir:
[int] CompareTo([Object]$Other) {
# Implementation
}
Arayüzün gerektirdiği imza, referans belgelerde listelenmiştir.
Sıcaklık için sınıf yalnızca sınıfın iki örneğinin karşılaştırılmasını desteklemelidir. Derece özelliğinin temel türü, farklı bir ölçeğe dönüştürüldüğünde bile kayan noktalı bir sayı olduğundan, yöntem, gerçek karşılaştırma için temel türe güvenebilir.
[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())
}
Sıcaklık sınıfının son tanımı şöyledir:
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
}
Tam tanımla kullanıcılar, PowerShell'deki sınıfın örneklerini herhangi bir yerleşik tür gibi biçimlendirebilir ve karşılaştırabilir.
$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
Örnek 3 - Genel bir temel sınıftan miras alma
Bu örnek, System.Collections.Generic.List gibi genel bir sınıftan nasıl türetebileceğinizi gösterir.
Type parametresi olarak yerleşik bir sınıfın kullanılması
Aşağıdaki kod bloğunu çalıştırın. Tür parametresi ayrıştırma sırasında zaten tanımlanmış olduğu sürece yeni bir sınıfın genel bir türden nasıl miras alabileceğini gösterir.
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
Type parametresi olarak özel bir sınıf kullanma
Sonraki kod bloğu ilk olarak tek örnek özelliğine ve ToString() yöntemine sahip yeni bir sınıf olan ExampleItem'i tanımlar. Daha sonra, System.Collections.Generic.List temel sınıfından miras alan ExampleItemList sınıfını, type parametresi olarak ExampleItem ile tanımlar.
Kod bloğunun tamamını kopyalayın ve tek bir ifade olarak çalıştırın.
class ExampleItem {
[string] $Name
[string] ToString() { return $this.Name }
}
class ExampleItemList : System.Collections.Generic.List[ExampleItem] {}
ParentContainsErrorRecordException: An error occurred while creating the pipeline.
PowerShell henüz ExampleItem sınıfını çalışma zamanına yüklemediğinden kod bloğunun tamamını çalıştırmak bir hataya neden olur. Henüz System.Collections.Generic.List temel sınıfı için tür parametresi olarak sınıf adını kullanamazsınız.
Aşağıdaki kod bloklarını tanımlandıkları sırayla çalıştırın.
class ExampleItem {
[string] $Name
[string] ToString() { return $this.Name }
}
class ExampleItemList : System.Collections.Generic.List[ExampleItem] {}
Bu sefer PowerShell herhangi bir hata ortaya çıkarmıyor. Artık her iki sınıf da tanımlanmıştır. Yeni sınıfın davranışını görüntülemek için aşağıdaki kod bloğunu çalıştırın.
$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
Bir modülde özel tür parametresiyle genel türetme
Aşağıdaki kod blokları, type parametresi için özel bir tür kullanan genel bir temel sınıftan miras alan bir sınıfı nasıl tanımlayabileceğinizi gösterir.
Aşağıdaki kod bloğunu GenericExample.psd1 olarak kaydedin.
@{
RootModule = 'GenericExample.psm1'
ModuleVersion = '0.1.0'
GUID = '2779fa60-0b3b-4236-b592-9060c0661ac2'
}
Aşağıdaki kod bloğunu GenericExample.InventoryItem.psm1 olarak kaydedin.
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))"
}
}
Aşağıdaki kod bloğunu GenericExample.psm1 olarak kaydedin.
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()
Yararlı ipucu
Kök modül, özel türleri PowerShell'in tür hızlandırıcılarına ekler. Bu model, modül kullanıcılarının, önce using module deyimini kullanmaya gerek kalmadan IntelliSense'e anında erişmesine ve özel türler için otomatik tamamlamaya olanak sağlar.
Bu kalıp hakkında daha fazla bilgi için about_Classes'ın "Tür hızlandırıcılarla dışarı aktarma" bölümüne bakın.
Modülü içe aktarın ve çıktıyı doğrulayın.
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
InventoryItem sınıfı Inventory sınıfından farklı bir modül dosyasında tanımlandığından modül hatasız yükleniyor. Her iki sınıf da modül kullanıcılarına açıktır.
Bir temel sınıfın miras alınması
Bir sınıf bir temel sınıftan miras aldığında, temel sınıfın özelliklerini ve yöntemlerini miras alır. Temel sınıf yapıcılarını doğrudan miras almaz ancak onları çağırabilir.
Temel sınıf PowerShell yerine .NET'te tanımlandığında şunları unutmayın:
- PowerShell sınıfları, mühürlü sınıflardan miras alınamaz.
- Genel bir temel sınıftan miras alırken, genel sınıfın type parametresi türetilmiş sınıf olamaz. Türetilmiş sınıfın type parametresi olarak kullanılması ayrıştırma hatasına neden olur.
Türetilmiş sınıflarda kalıtımın ve geçersiz kılmanın nasıl çalıştığını görmek için Örnek 1'e bakın.
Türetilmiş sınıf yapıcıları
Türetilmiş sınıflar, temel sınıfın yapıcılarını doğrudan miras almazlar. Temel sınıf bir varsayılan kurucu tanımlıyorsa ve türetilmiş sınıf herhangi bir kurucu tanımlamıyorsa, türetilmiş sınıfın yeni örnekleri temel sınıfın varsayılan kurucusunu kullanır. Temel sınıf varsayılan bir kurucu tanımlamıyorsa, türetilmiş sınıfın en az bir kurucuyu açıkça tanımlaması gerekir.
Türetilmiş sınıf kurucuları, base anahtar sözcüğüyle temel sınıftan bir kurucuyu çağırabilir. Türetilmiş sınıf açıkça temel sınıftan bir kurucuyu çağırmazsa, bunun yerine temel sınıf için varsayılan kurucuyu çağırır.
Varsayılan olmayan bir temel kurucuyu çağırmak için, yapıcı parametrelerinden sonra ve gövde bloğundan önce : base( ekleyin.
class <derived-class> : <base-class> {
<derived-class>(<derived-parameters>) : <base-class>(<base-parameters>) {
# initialization code
}
}
Temel sınıf yapıcısını çağıran bir yapıcıyı tanımlarken parametreler aşağıdaki öğelerden herhangi biri olabilir:
- Türetilmiş sınıf yapıcısındaki herhangi bir parametrenin değişkeni.
- Herhangi bir statik değer.
- Parametre türünün değerini değerlendiren herhangi bir ifade.
Örnek 1'deki Illustration sınıfı, türetilmiş bir sınıfın temel sınıf yapıcılarını nasıl kullanabileceğini gösterir.
Türetilmiş sınıf yöntemleri
Bir sınıf bir temel sınıftan türetildiğinde, temel sınıfın yöntemlerini ve bunların aşırı yüklerini miras alır. Gizli yöntemler de dahil olmak üzere temel sınıfta tanımlanan tüm yöntem aşırı yüklemeleri türetilmiş sınıfta mevcuttur.
Türetilmiş bir sınıf, devralınan yöntem aşırı yüklemesini sınıf tanımında yeniden tanımlayarak geçersiz kılabilir. Aşırı yüklemeyi geçersiz kılmak için parametre türlerinin temel sınıfla aynı olması gerekir. Aşırı yük için çıkış tipi farklı olabilir.
Yapıcılardan farklı olarak yöntemler, yöntem için temel sınıf aşırı yüklemesini çağırmak amacıyla : base( sözdizimini kullanamaz. Türetilmiş sınıftaki yeniden tanımlanan aşırı yük, temel sınıf tarafından tanımlanan aşırı yükün tamamen yerini alır. Bir örneğin temel sınıf yöntemini çağırmak için, yöntemi çağırmadan önce örnek değişkenini ($this) temel sınıfa aktarın.
Aşağıdaki kod parçası, türetilmiş bir sınıfın temel sınıf yöntemini nasıl çağırabileceğini gösterir.
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
Türetilmiş bir sınıfın devralınan yöntemleri nasıl geçersiz kıldığını gösteren genişletilmiş bir örnek için Örnek 1'deki Illustration sınıfına bakın.
Türetilmiş sınıf özellikleri
Bir sınıf bir temel sınıftan türetildiğinde, temel sınıfın özelliklerini miras alır. Gizli özellikler de dahil olmak üzere temel sınıfta tanımlanan tüm özellikler türetilmiş sınıfta mevcuttur.
Türetilmiş bir sınıf, miras alınan bir özelliği sınıf tanımında yeniden tanımlayarak geçersiz kılabilir. Türetilmiş sınıftaki özellik, yeniden tanımlanmış türü ve varsa varsayılan değeri kullanır. Devralınan özellik varsayılan bir değer tanımladıysa ve yeniden tanımlanan özellik tanımlamıyorsa, devralınan özelliğin varsayılan değeri yoktur.
Türetilmiş bir sınıf, statik bir özelliği geçersiz kılmazsa, statik özelliğe türetilmiş sınıf aracılığıyla erişildiğinde, temel sınıfın statik özelliğine de erişilir. Özellik değerinin türetilmiş sınıf aracılığıyla değiştirilmesi, temel sınıftaki değeri değiştirir. Statik özelliği geçersiz kılmayan diğer türetilmiş sınıflar da temel sınıftaki özelliğin değerini kullanır. Miras alınan bir statik özelliğin değerinin, özelliği geçersiz kılmayan bir sınıfta güncellenmesi, aynı temel sınıftan türetilen sınıflar üzerinde istenmeyen etkilere neden olabilir.
Örnek 1, temel sınıf özelliklerini devralan, genişleten ve geçersiz kılan türetilmiş sınıfların nasıl olduğunu gösterir.
Jeneriklerden türetme
Bir sınıf genel bir sınıftan türetildiğinde, PowerShell türetilmiş sınıfı ayrıştırmadan önce type parametresinin zaten tanımlanmış olması gerekir. Jenerik için type parametresi aynı dosya veya kod bloğunda tanımlanan bir PowerShell sınıfı veya numaralandırmasıysa PowerShell bir hata oluşturur.
Type parametresi olarak özel bir türe sahip genel bir temel sınıftan bir sınıf türetmek için, type parametresi için sınıfı veya numaralandırmayı farklı bir dosya veya modülde tanımlayın ve türü yüklemek için using module deyimini kullanın. tanım.
Genel bir temel sınıftan nasıl miras alınacağını gösteren bir örnek için Örnek 3'e bakın.
Miras alınacak faydalı sınıflar
PowerShell modülleri yazarken devralmanın yararlı olabileceği birkaç sınıf vardır. Bu bölüm birkaç temel sınıfı ve bunlardan türetilen bir sınıfın ne için kullanılabileceğini listeler.
- System.Attribute - Değişkenler, parametreler, sınıf ve numaralandırma tanımları ve daha fazlası için kullanılabilecek nitelikleri tanımlamak üzere sınıflar türetin.
- System.Management.Automation.ArgumentTransformationAttribute - Bir değişkene veya parametreye ilişkin girişi belirli bir veri türüne dönüştürmeyi işlemek için sınıflar türetin.
- System.Management.Automation.ValidateArgumentsAttribute - Değişkenlere, parametrelere ve sınıf özelliklerine özel doğrulama uygulamak için sınıflar türetin.
- System.Collections.Generic.List - Belirli bir veri türündeki listeleri oluşturmayı ve yönetmeyi kolaylaştırmak için sınıflar türetin.
- System.Exception - Özel hataları tanımlamak için sınıfları türetin.
Arayüzlerin uygulanması
Bir arabirimi uygulayan bir PowerShell sınıfı, o arabirimin tüm üyelerini uygulamalıdır. Uygulama arayüzü üyelerinin atlanması, komut dosyasında ayrıştırma zamanı hatasına neden olur.
Not
PowerShell, PowerShell betiğinde yeni arayüzlerin bildirilmesini desteklemez. Bunun yerine, arayüzlerin .NET kodunda bildirilmesi ve Add-Type cmdlet'i veya using Assembly deyimiyle oturuma eklenmesi gerekir.
Bir sınıf bir arayüzü uyguladığında, o arayüzü uygulayan diğer sınıflar gibi kullanılabilir. Bazı komutlar ve işlemler, desteklenen türlerini belirli bir arayüzü uygulayan sınıflarla sınırlar.
Arayüzlerin örnek uygulamasını incelemek için Örnek 2'ye bakın.
Uygulamaya yönelik faydalı arayüzler
PowerShell modüllerini yazarken devralmanın yararlı olabileceği birkaç arayüz sınıfı vardır. Bu bölüm birkaç temel sınıfı ve bunlardan türetilen bir sınıfın ne için kullanılabileceğini listeler.
- System.IEquatable - Bu arayüz, kullanıcıların sınıfın iki örneğini karşılaştırmasına olanak tanır. Bir sınıf bu arayüzü uygulamadığında PowerShell, referans eşitliğini kullanarak iki örnek arasındaki denkliği kontrol eder. Başka bir deyişle, iki örnekteki özellik değerleri aynı olsa bile sınıfın bir örneği yalnızca kendisine eşittir.
- System.IComparable - Bu arayüz, kullanıcıların sınıfın örneklerini
-le,-lt,-geile karşılaştırmasına olanak tanır ve-gtkarşılaştırma operatörleri. Bir sınıf bu arayüzü uygulamadığında, bu operatörler bir hataya neden olur. - System.IFormattable - Bu arayüz, kullanıcıların sınıfın örneklerini farklı dizeler halinde biçimlendirmesine olanak tanır. Bu, bütçe öğeleri, bibliyografyalar ve sıcaklıklar gibi birden fazla standart dize temsiline sahip sınıflar için kullanışlıdır.
- System.IConvertible - Bu arayüz, kullanıcıların sınıfın örneklerini diğer çalışma zamanı türlerine dönüştürmesine olanak tanır. Bu, temel bir sayısal değere sahip olan veya bir değere dönüştürülebilen sınıflar için kullanışlıdır.
Sınırlamalar
PowerShell, komut dosyası kodunda arabirimlerin tanımlanmasını desteklemez.
Geçici çözüm: C#'ta arayüzleri tanımlayın ve arayüzleri tanımlayan derlemeye başvurun.
PowerShell sınıfları yalnızca bir temel sınıftan miras alabilir.
Geçici Çözüm: Sınıf mirası geçişlidir. Türetilmiş bir sınıf, bir temel sınıfın özelliklerini ve yöntemlerini elde etmek için başka bir türetilmiş sınıftan miras alabilir.
Genel bir sınıftan veya arayüzden miras alırken, genelin type parametresi önceden tanımlanmış olmalıdır. Bir sınıf kendisini bir sınıfın veya arayüzün tür parametresi olarak tanımlayamaz.
Geçici çözüm: Genel bir temel sınıftan veya arayüzden türetmek için, özel türü farklı bir
.psm1dosyasında tanımlayın ve türü yüklemek içinusing moduledeyimini kullanın. Özel bir türün, bir jenerikten devralınırken kendisini tür parametresi olarak kullanmasına yönelik bir geçici çözüm yoktur.
Ayrıca Bakınız
- about_Classes
- about_Classes_Constructors
- about_Classes_Methods
- about_Classes_Properties