-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path01_ClassMechanics.ps1
More file actions
105 lines (92 loc) · 3.94 KB
/
Copy path01_ClassMechanics.ps1
File metadata and controls
105 lines (92 loc) · 3.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<#
.SYNOPSIS
OOP Reference: Class Mechanics
.DESCRIPTION
Topic: PowerShell Class Mechanics
Category: Fundamentals
Agent Task: Study, extend, and add Pester tests for each concept below.
Do not refactor the examples — extend them.
Done Conditions:
- Each class loads without error in PS 7.x
- Pester tests cover: static ctor fires once, hidden member accessible via code but not Get-Member,
[void] method produces no pipeline output, load order enforced by dot-source order
- Tests pass: Invoke-Pester -Output Detailed
Non-Scope:
- Do not add GUI, remote, or module-level concerns
- Do not convert to a module manifest yet
#>
# ---------------------------------------------------------------------------
# 1. Static Constructor / Type Initializer
# ---------------------------------------------------------------------------
# Fires exactly once when the type is first accessed. No parameters allowed.
class CryptoRegistry {
static [hashtable]$Algorithms
static [bool]$Initialized
static CryptoRegistry() {
[CryptoRegistry]::Algorithms = @{
'AES-256-GCM' = [System.Security.Cryptography.AesGcm]
'AES-256-CBC' = [System.Security.Cryptography.Aes]
'SHA-256' = [System.Security.Cryptography.SHA256]
'SHA-512' = [System.Security.Cryptography.SHA512]
'HMAC-SHA-256' = [System.Security.Cryptography.HMACSHA256]
}
[CryptoRegistry]::Initialized = $true
}
static [bool] IsSupported([string]$algo) {
return [CryptoRegistry]::Algorithms.ContainsKey($algo)
}
}
# ---------------------------------------------------------------------------
# 2. Class Load Order
# ---------------------------------------------------------------------------
# Parent must be defined before child in the same file.
# In multi-file projects: dot-source in dependency order.
class CryptoBase {
[string]$Algorithm
CryptoBase([string]$algo) { $this.Algorithm = $algo }
}
class DerivedCrypto : CryptoBase {
DerivedCrypto() : base('AES-256-GCM') { }
}
# ---------------------------------------------------------------------------
# 3. hidden vs private — hidden is NOT private
# ---------------------------------------------------------------------------
class SecretHolder {
hidden [string]$_secret = "hidden but reachable"
[string] GetSecret() { return $this._secret }
}
# Demonstrate: $obj._secret still works from outside the class
# Demonstrate: $obj | Get-Member does NOT show _secret
# ---------------------------------------------------------------------------
# 4. [void] Return — suppresses pipeline output
# ---------------------------------------------------------------------------
class VoidDemo {
# Without [void]: Write-Host output leaks into the pipeline return value
[void] SideEffect([string]$msg) {
Write-Host $msg
}
# Without [void] this would return $true to the caller
[void] MutateBuffer([byte[]]$buffer) {
for ($i = 0; $i -lt $buffer.Length; $i++) {
$buffer[$i] = $buffer[$i] -bxor 0xFF
}
}
[int] TypedReturn([int]$a, [int]$b) {
return $a + $b
}
}
# ---------------------------------------------------------------------------
# 5. Method Resolution — type coercion behavior
# ---------------------------------------------------------------------------
class OverloadCoercionDemo {
[string] Identify([string]$x) { return "string:$x" }
[string] Identify([byte[]]$x) { return "bytes:$($x.Length)" }
[string] Identify([int]$x) { return "int:$x" }
}
# Usage examples (run interactively or in Pester):
# $d = [OverloadCoercionDemo]::new()
# $d.Identify("hello") -> string overload
# $d.Identify(42) -> int overload
# $d.Identify([byte[]]@(1,2)) -> byte[] overload
# $d.Identify($null) -> THROWS: ambiguous between string and byte[]
# Fix: [string]$null or [byte[]]$null