about_Classes_Constructors

Deskripsi singkat

Menjelaskan cara menentukan konstruktor untuk kelas PowerShell.

Deskripsi panjang

Konstruktor memungkinkan Anda mengatur nilai default dan memvalidasi logika objek saat membuat instans kelas. Konstruktor memiliki nama yang sama dengan kelas . Konstruktor mungkin memiliki parameter, untuk menginisialisasi anggota data objek baru.

Konstruktor kelas PowerShell didefinisikan sebagai metode khusus pada kelas . Mereka berulah sama dengan metode kelas PowerShell dengan pengecualian berikut:

  • Konstruktor tidak memiliki jenis output. Mereka tidak dapat menggunakan return kata kunci.
  • Konstruktor selalu memiliki nama yang sama dengan kelas.
  • Konstruktor tidak dapat dipanggil secara langsung. Mereka hanya berjalan saat instans dibuat.
  • Konstruktor tidak pernah muncul dalam output untuk Get-Member cmdlet.

Untuk informasi selengkapnya tentang metode kelas PowerShell, lihat about_Classes_Methods.

Kelas dapat memiliki nol atau lebih konstruktor yang ditentukan. Jika tidak ada konstruktor yang ditentukan, kelas diberi konstruktor tanpa parameter default. Konstruktor ini menginisialisasi semua anggota ke nilai default mereka. Jenis objek dan string diberi nilai null. Saat Anda menentukan konstruktor, tidak ada konstruktor tanpa parameter default yang dibuat. Buat konstruktor tanpa parameter jika diperlukan.

Anda juga dapat menentukan konstruktor statis tanpa parameter.

Sintaks

Konstruktor kelas menggunakan sintaks berikut:

Sintaks konstruktor default

<class-name> () [: base([<params>])] {
    <body>
}

Sintaks konstruktor statis

static <class-name> () [: base([<params>])] {
    <body>
}

Sintaks konstruktor berparameter (satu baris)

<class-name> ([[<parameter-type>]$<parameter-name>[, [<parameter-type>]$<parameter-name>...]]) [: base([<params>])] {
    <body>
}

Sintaks konstruktor berparameter (multibaris)

<class-name> (
    [<parameter-type>]$<parameter-name>[,
    [<parameter-type>]$<parameter-name>...]
) [: base([<params>])] {
    <body>
}

Contoh

Contoh 1 - Menentukan kelas dengan konstruktor default

Kelas ExampleBook1 tidak menentukan konstruktor. Sebaliknya, ia menggunakan konstruktor default otomatis.

class ExampleBook1 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn
}

[ExampleBook1]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
                0 1/1/0001 12:00:00 AM

Catatan

Nilai default untuk properti Nama dan Penulis adalah $null karena ditik sebagai string, yang merupakan jenis referensi. Properti lain memiliki nilai default untuk jenis yang ditentukan, karena properti jenis nilai. Untuk informasi selengkapnya tentang nilai default untuk properti, lihat "Nilai properti default" di about_Classes_Properties.

Contoh 2 - Mengesampingkan konstruktor default

ExampleBook2 secara eksplisit menentukan konstruktor default, mengatur nilai untuk PublishedOn ke tanggal dan Halaman saat ini ke 1.

class ExampleBook2 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn

    ExampleBook2() {
        $this.PublishedOn = (Get-Date).Date
        $this.Pages       = 1
    }
}

[ExampleBook2]::new()
Name Author Pages PublishedOn
---- ------ ----- -----------
                1 11/1/2023 12:00:00 AM

Contoh 3 - Menentukan kelebihan beban konstruktor

Kelas ExampleBook3 mendefinisikan tiga kelebihan beban konstruktor, memungkinkan pengguna untuk membuat instans kelas dari hashtable, dengan meneruskan setiap nilai properti, dan dengan meneruskan nama buku dan penulis. Kelas tidak menentukan konstruktor default.

class ExampleBook3 {
    [string]   $Name
    [string]   $Author
    [int]      $Pages
    [datetime] $PublishedOn

    ExampleBook3([hashtable]$Info) {
        switch ($Info.Keys) {
            'Name'        { $this.Name        = $Info.Name }
            'Author'      { $this.Author      = $Info.Author }
            'Pages'       { $this.Pages       = $Info.Pages }
            'PublishedOn' { $this.PublishedOn = $Info.PublishedOn }
        }
    }

    ExampleBook3(
        [string]   $Name,
        [string]   $Author,
        [int]      $Pages,
        [datetime] $PublishedOn
    ) {
        $this.Name        = $Name
        $this.Author      = $Author
        $this.Pages       = $Pages
        $this.PublishedOn = $PublishedOn
    }

    ExampleBook3([string]$Name, [string]$Author) {
        $this.Name   = $Name
        $this.Author = $Author
    }
}

[ExampleBook3]::new(@{
    Name        = 'The Hobbit'
    Author      = 'J.R.R. Tolkien'
    Pages       = 310
    PublishedOn = '1937-09-21'
})
[ExampleBook3]::new('The Hobbit', 'J.R.R. Tolkien', 310, '1937-09-21')
[ExampleBook3]::new('The Hobbit', 'J.R.R. Tolkien')
[ExampleBook3]::new()
Name       Author         Pages PublishedOn
----       ------         ----- -----------
The Hobbit J.R.R. Tolkien   310 9/21/1937 12:00:00 AM
The Hobbit J.R.R. Tolkien   310 9/21/1937 12:00:00 AM
The Hobbit J.R.R. Tolkien     0 1/1/0001 12:00:00 AM

MethodException:
Line |
  42 |  [ExampleBook3]::new()
     |  ~~~~~~~~~~~~~~~~~~~~~
     | Cannot find an overload for "new" and the argument count: "0".

Memanggil konstruktor default mengembalikan pengecualian metode. Konstruktor default otomatis hanya ditentukan untuk kelas ketika kelas tidak menentukan konstruktor apa pun. Karena ExampleBook3 mendefinisikan beberapa kelebihan beban, konstruktor default tidak secara otomatis ditambahkan ke kelas .

Contoh 4 - Konstruktor rantai dengan metode bersama

Contoh ini menunjukkan bagaimana Anda dapat menulis kode bersama yang dapat digunakan kembali untuk konstruktor. Kelas PowerShell tidak dapat menggunakan penautan konstruktor, sehingga kelas contoh ini mendefinisikan Init() metode sebagai gantinya. Metode ini memiliki beberapa kelebihan beban. Kelebihan beban dengan lebih sedikit parameter memanggil kelebihan beban yang lebih eksplisit dengan nilai default untuk parameter yang tidak ditentukan.

class ExampleBook4 {
    [string]   $Name
    [string]   $Author
    [datetime] $PublishedOn
    [int]      $Pages

    ExampleBook4() {
        $this.Init()
    }
    ExampleBook4([string]$Name) {
        $this.Init($Name)
    }
    ExampleBook4([string]$Name, [string]$Author) {
        $this.Init($Name, $Author)
    }
    ExampleBook4([string]$Name, [string]$Author, [datetime]$PublishedOn) {
        $this.Init($Name, $Author, $PublishedOn)
    }
    ExampleBook4(
      [string]$Name,
      [string]$Author,
      [datetime]$PublishedOn,
      [int]$Pages
    ) {
        $this.Init($Name, $Author, $PublishedOn, $Pages)
    }

    hidden Init() {
        $this.Init('Unknown')
    }
    hidden Init([string]$Name) {
        $this.Init($Name, 'Unknown')
    }
    hidden Init([string]$Name, [string]$Author) {
        $this.Init($Name, $Author, (Get-Date).Date)
    }
    hidden Init([string]$Name, [string]$Author, [datetime]$PublishedOn) {
        $this.Init($Name, $Author, $PublishedOn, 1)
    }
    hidden Init(
        [string]$Name,
        [string]$Author,
        [datetime]$PublishedOn,
        [int]$Pages
      ) {
        $this.Name        = $Name
        $this.Author      = $Author
        $this.PublishedOn = $PublishedOn
        $this.Pages       = $Pages
    }
}

[ExampleBook4]::new()
[ExampleBook4]::new('The Hobbit')
[ExampleBook4]::new('The Hobbit', 'J.R.R. Tolkien')
[ExampleBook4]::new('The Hobbit', 'J.R.R. Tolkien', (Get-Date '1937-9-21'))
[ExampleBook4]::new(
    'The Hobbit',
    'J.R.R. Tolkien',
    (Get-Date '1937-9-21'),
    310
)
Name       Author         PublishedOn           Pages
----       ------         -----------           -----
Unknown    Unknown        11/1/2023 12:00:00 AM     1
The Hobbit Unknown        11/1/2023 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 11/1/2023 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 9/21/1937 12:00:00 AM     1
The Hobbit J.R.R. Tolkien 9/21/1937 12:00:00 AM   310

Contoh 5 - Konstruktor kelas turunan

Contoh berikut menggunakan kelas yang menentukan konstruktor statis, default, dan parameter untuk kelas dasar dan kelas turunan yang mewarisi dari kelas dasar.

class BaseExample {
    static [void] DefaultMessage([type]$Type) {
        Write-Verbose "[$($Type.Name)] default constructor"
    }

    static [void] StaticMessage([type]$Type) {
        Write-Verbose "[$($Type.Name)] static constructor"
    }

    static [void] ParamMessage([type]$Type, [object]$Value) {
        Write-Verbose "[$($Type.Name)] param constructor ($Value)"
    }

    static BaseExample() { [BaseExample]::StaticMessage([BaseExample])  }
    BaseExample()        { [BaseExample]::DefaultMessage([BaseExample]) }
    BaseExample($Value)  { [BaseExample]::ParamMessage([BaseExample], $Value) }
}

class DerivedExample : BaseExample {
    static DerivedExample() { [BaseExample]::StaticMessage([DerivedExample])  }
           DerivedExample() { [BaseExample]::DefaultMessage([DerivedExample]) }

    DerivedExample([int]$Number) : base($Number) {
        [BaseExample]::ParamMessage([DerivedExample], $Number)
    }
    DerivedExample([string]$String) {
        [BaseExample]::ParamMessage([DerivedExample], $String)
    }
}

Blok berikut menunjukkan pesan verbose untuk memanggil konstruktor kelas dasar. Pesan konstruktor statis hanya dipancarkan saat pertama kali instans kelas dibuat.

PS> $VerbosePreference = 'Continue'
PS> $b = [BaseExample]::new()

VERBOSE: [BaseExample] static constructor
VERBOSE: [BaseExample] default constructor

PS> $b = [BaseExample]::new()

VERBOSE: [BaseExample] default constructor

PS> $b = [BaseExample]::new(1)

VERBOSE: [BaseExample] param constructor (1)

Blok berikutnya menunjukkan pesan verbose untuk memanggil konstruktor kelas turunan dalam sesi baru. Pertama kali konstruktor kelas turunan dipanggil, konstruktor statis untuk kelas dasar dan kelas turunan dipanggil. Konstruktor tersebut tidak dipanggil lagi dalam sesi. Konstruktor untuk kelas dasar selalu berjalan sebelum konstruktor untuk kelas turunan.

PS> $VerbosePreference = 'Continue'
PS> $c = [DerivedExample]::new()

VERBOSE: [BaseExample] static constructor
VERBOSE: [DerivedExample] static constructor
VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] default constructor

PS> $c = [DerivedExample]::new()

VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] default constructor

PS> $c = [DerivedExample]::new(1)

VERBOSE: [BaseExample] param constructor (1)
VERBOSE: [DerivedExample] param constructor (1)

PS> $c = [DerivedExample]::new('foo')

VERBOSE: [BaseExample] default constructor
VERBOSE: [DerivedExample] param constructor (foo)

Urutan eksekusi konstruktor

Saat kelas membuat instans, kode untuk satu atau beberapa konstruktor dijalankan.

Untuk kelas yang tidak mewarisi dari kelas lain, urutannya adalah:

  1. Konstruktor statis untuk kelas .
  2. Konstruktor yang berlaku kelebihan beban untuk kelas .

Untuk kelas turunan yang mewarisi dari kelas lain, pemesanannya adalah:

  1. Konstruktor statis untuk kelas dasar.
  2. Konstruktor statis untuk kelas turunan.
  3. Jika konstruktor kelas turunan secara eksplisit memanggil konstruktor dasar kelebihan beban, konstruktor tersebut menjalankan konstruktor tersebut untuk kelas dasar. Jika tidak secara eksplisit memanggil konstruktor dasar, konstruktor tersebut menjalankan konstruktor default untuk kelas dasar.
  4. Kelebihan konstruktor yang berlaku untuk kelas turunan.

Dalam semua kasus, konstruktor statis hanya berjalan sekali dalam satu sesi.

Untuk contoh perilaku dan pengurutan konstruktor, lihat Contoh 5.

Konstruktor tersembunyi

Anda dapat menyembunyikan konstruktor kelas dengan mendeklarasikannya dengan hidden kata kunci. Konstruktor kelas tersembunyi adalah:

  • Tidak disertakan dalam output default untuk kelas .
  • Tidak termasuk dalam daftar anggota kelas yang Get-Member dikembalikan oleh cmdlet. Untuk menampilkan properti tersembunyi dengan Get-Member, gunakan parameter Paksa .
  • Tidak ditampilkan dalam penyelesaian tab atau IntelliSense kecuali penyelesaian terjadi di kelas yang menentukan properti tersembunyi.
  • Anggota publik kelas. Mereka dapat diakses dan dimodifikasi. Menyembunyikan properti tidak membuatnya privat. Ini hanya menyembunyikan properti seperti yang dijelaskan di poin sebelumnya.

Catatan

Saat Anda menyembunyikan konstruktor apa pun, new() opsi dihapus dari IntelliSense dan hasil penyelesaian.

Untuk informasi selengkapnya tentang hidden kata kunci, lihat about_Hidden.

Konstruktor statik

Anda dapat menentukan konstruktor sebagai milik kelas itu sendiri alih-alih instans kelas dengan mendeklarasikan konstruktor dengan static kata kunci. Konstruktor kelas statis:

  • Hanya panggil pertama kali instans kelas dibuat dalam sesi.
  • Tidak dapat memiliki parameter apa pun.
  • Tidak dapat mengakses properti atau metode instans dengan $this variabel .

Konstruktor untuk kelas turunan

Ketika kelas mewarisi dari kelas lain, konstruktor dapat memanggil konstruktor dari kelas dasar dengan base kata kunci. 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.

Untuk contoh konstruktor pada kelas turunan, lihat Contoh 5.

Konstruktor rantai

Tidak seperti C#, konstruktor kelas PowerShell tidak dapat menggunakan penautan dengan : this(<parameters>) sintaks. Untuk mengurangi duplikasi kode, gunakan metode tersembunyi Init() dengan beberapa kelebihan beban ke efek yang sama. Contoh 4 menunjukkan kelas menggunakan pola ini.

Menambahkan properti dan metode instans dengan Update-TypeData

Selain mendeklarasikan properti dan metode langsung dalam definisi kelas, Anda dapat menentukan properti untuk instans kelas di konstruktor statis menggunakan Update-TypeData cmdlet.

Gunakan cuplikan ini sebagai titik awal untuk pola. Ganti teks tempat penampung dalam tanda kurung sudut sesuai kebutuhan.

class <class-name> {
    static [hashtable[]] $MemberDefinitions = @(
        @{
            Name       = '<member-name>'
            MemberType = '<member-type>'
            Value      = <member-definition>
        }
    )

    static <class-name>() {
        $TypeName = [<class-name>].Name
        foreach ($Definition in [<class-name>]::MemberDefinitions) {
            Update-TypeData -TypeName $TypeName @Definition
        }
    }
}

Tip

Add-Member Cmdlet dapat menambahkan properti dan metode ke kelas dalam konstruktor non-statis, tetapi cmdlet dijalankan setiap kali konstruktor dipanggil. Menggunakan Update-TypeData dalam konstruktor statis memastikan bahwa kode untuk menambahkan anggota ke kelas hanya perlu berjalan sekali dalam sesi.

Hanya tambahkan properti ke kelas di konstruktor non-statis saat tidak dapat didefinisikan dengan Update-TypeData, seperti properti baca-saja.

Untuk informasi selengkapnya tentang menentukan metode instans dengan Update-TypeData, lihat about_Classes_Methods. Untuk informasi selengkapnya tentang menentukan properti instans dengan Update-TypeData, lihat about_Classes_Properties.

Batasan

Konstruktor kelas PowerShell memiliki batasan berikut:

  • Penautan konstruktor tidak diimplementasikan.

    Solusi sementara: Tentukan metode tersembunyi Init() dan panggil dari dalam konstruktor.

  • Parameter konstruktor tidak dapat menggunakan atribut apa pun, termasuk atribut validasi.

    Solusi sementara: Menetapkan ulang parameter dalam isi konstruktor dengan atribut validasi.

  • Parameter konstruktor tidak dapat menentukan nilai default. Parameter selalu wajib.

    Penanganan masalah: Tidak ada.

  • Jika ada kelebihan beban konstruktor yang disembunyikan, setiap kelebihan beban untuk konstruktor diperlakukan sebagai tersembunyi juga.

    Penanganan masalah: Tidak ada.

Lihat juga