类名称为变量

时间:2019-09-03 08:14:34

标签: powershell class variables

好的,我一般对OOP完全陌生,并尝试在PowerShell 5.0中学习它。我有很棒的工作代码。

class Animal {
    [string]$name
    [int]$legs
    [int]$age
    [int]$weightLbs
    [int]$heightInches

    Animal() {
    }
    Animal([string]$name) {
        $this.name = $name 
    }

    [string]Jump() {
        return  "look at that $($this.ToString()) jump!"
    }

    [string]Speak() {
        throw [notImplementedException]::New('Speak method should be overridden in child class')
    }
}

class Dog : Animal {
    [int]$tailLength

    Dog() {
    }
    Dog([string]$name)  : base($name) {
    }

    [int]AgeDogYears() {
        return $this.age * 7
    }
    [string]Speak() {
        return 'woof!'
    }
}


CLS

$rottweiler = [Dog]::new('Rottweiler')
$rottweiler.AgeDogYears()
$rottweiler.Jump()
$rottweiler.Speak()

但是,在我实际上需要实现的代码中,我将从XML中提取数据,并且需要基于该数据引用特定的Class。使用函数时,我可以在从XML数据分配的变量中有一个函数名,然后调用该函数。但是当我在类上尝试类似的东西时……

$className = 'Dog'
$boxer = [$className]::new('Boxer')

...这是不行的。是否有一种机制,或者我是否必须使用Switch语句之类的东西并在那里找到所有可能的类名,然后需要将该语句与我创建的任何新类进行协调?

另外,如果存在“将类名作为变量”选项,那么如果XML中存在类型,我将需要进行测试以确保该类确实存在。例如,如果XML有上帝,而Class应该是Dog。到目前为止,除了Try / Catch之外,我还没有找到一种测试类是否存在的方法。这是我唯一的选择,还是有更好的方法?我尝试将“尝试/捕获”限制为意外内容。因此,例如,我不对Remove-Item的文件夹路径采用参数,而是将其包装在Try / Catch中,首先测试路径,如果找不到目标,则在日志中提供错误,然后对目标具有禁止删除权限的对象使用Try / Catch。对我来说似乎是一种更好的方法。

编辑:好吧,尝试在@josefz的帖子上进行推断,我尝试了此操作和一些变体,以获取每次对变量中的类或变量名称的引用。我感觉我太近了。

$newClass = 'Dog'
$newDog = 'Boxer'

New-Variable -name:($newDog) -value:$($newClass -as [type])::new($newDog)
(Get-Variable -name:($newDog)).Jump()

EDIT2:所以,我仍然似乎在将类与New-Variable集成时遇到问题,但是对于测试是否存在类,这可以解决问题。这样就解决了。

if (($testClass -as [type])) {
    Write-Host "$testClass is a valid class"
} else {
    Write-Host "$testClass is not a valid class"
}

此外,我可能最终将结果组织在哈希表中或类似的东西中,而不是单个变量中。而且也可以。

$dogs = @('rottweiler', 'boxer')
$dogObjects = @{}
foreach ($dog in $dogs) {
    $dogObjects.Add($dog, [Dog]::new($dog))
}
foreach ($key in $dogObjects.keys) {
    Write-Host "$($dogObjects.$key.Jump())"
}

1 个答案:

答案 0 :(得分:1)

更改

[string]Jump() {
    return  "look at that $($this.ToString()) jump!"
}

[string]Jump() {
    return  "look at that $($this.name) jump!"
}

您可以使用声明的类,例如如下:

$rottweiler = [Dog]::new('Rottweiler')
$rottweiler.AgeDogYears()
$rottweiler.Jump()
$rottweiler.Speak()

# another use case:
$auxObject=@"
species,breed,note
Dog,husky,valid
Int,beagle,invalid: ('Int' -as [type]) returns System.ValueType
NaN,collie,invalid: ('NaN' -as [type]) returns Null
Cat,bobtail,invalid: 'Cat' isn't defined yet as Animal class
Dog,bulldog,valid
"@ | ConvertFrom-Csv -Delimiter ','

foreach ( $aux in $auxObject) {
    $ClassType = $aux.Species -as [type]
    if ( $ClassType -and $ClassType.BaseType.FullName -eq 'Animal' ) {
        '---'
        $aDog = $ClassType::new($aux.Breed)
        $aDog.AgeDogYears()
        $aDog.Jump()
        $aDog.Speak()
    }
}

输出:.\SO\57767613.ps1

0
look at that Rottweiler jump!
woof!
---
0
look at that husky jump!
woof!
---
0
look at that bulldog jump!
woof!

编辑:另一个用例-哈希表

$Animals = @{}
foreach ( $aux in $auxObject) {
    $ClassType = $aux.Species -as [type]
    if ( $ClassType -and $ClassType.BaseType.FullName -eq 'Animal' ) {
        $Animals[$aux.breed] = $ClassType::new($aux.Breed)
    }
}

$Animals.Rottweiler.Jump()
$Animals.Rottweiler.Speak()

$Animals.Husky.Jump()
$Animals.Husky.Speak()

$aDog = 'bulldog'
$Animals.$aDog.Jump()
$Animals.$aDog.Speak()

输出D:\PShell\SO\57767613a.ps1

look at that Rottweiler jump!
woof!
look at that husky jump!
woof!
look at that bulldog jump!
woof!

注意

$Animals.$aDog | Get-Member
   TypeName: Dog

Name         MemberType Definition                    
----         ---------- ----------                    
AgeDogYears  Method     int AgeDogYears()             
Equals       Method     bool Equals(System.Object obj)
GetHashCode  Method     int GetHashCode()             
GetType      Method     type GetType()                
Jump         Method     string Jump()                 
Speak        Method     string Speak()                
ToString     Method     string ToString()             
age          Property   int age {get;set;}            
heightInches Property   int heightInches {get;set;}   
legs         Property   int legs {get;set;}           
name         Property   string name {get;set;}        
tailLength   Property   int tailLength {get;set;}     
weightLbs    Property   int weightLbs {get;set;}