PowerShell 中的函数重载

Posted

技术标签:

【中文标题】PowerShell 中的函数重载【英文标题】:Function overloading in PowerShell 【发布时间】:2011-04-25 20:08:10 【问题描述】:

你能在 PowerShell 中重载函数吗?

我想让我的函数接受一个字符串、数组或一些开关。

我想要的一个例子:

Backup-UsersData singleUser 备份-UsersData @('Alice', 'Bob', “乔”) 备份-UsersData -all

【问题讨论】:

“参数集”基本上相当于OO方法重载。由于 poewrshell 的类型强制繁重的解析器,它们有时会有点棘手。 【参考方案1】:

在 PowerShell 中函数没有重载。最后一个定义覆盖同一范围内的前一个或隐藏父范围内的前一个。因此,您应该创建一个函数并提供一种通过参数来区分其调用模式的方法。

在 V2 中,您可以使用高级功能,请参阅 help about_Functions_Advanced_Parameters 并避免在解决参数集歧义时进行一些手动编码:

# advanced function with 3 parameter sets
function Backup-UsersData
(
    [Parameter(Position=0, ParameterSetName="user")]
    [string]$user,
    [Parameter(Position=0, ParameterSetName="array")]
    [object[]]$array,
    [Parameter(Position=0, ParameterSetName="all")]
    [switch]$all
)

    # use this to get the parameter set name
    $PSCmdlet.ParameterSetName


# test
Backup-UsersData -user 'John'
Backup-UsersData 1, 2
Backup-UsersData -all

# OUTPUT:
# user
# array
# all

请注意,这种机制有时很奇怪。例如,在第一个测试中,我们必须明确指定参数名称-user。否则:

Backup-UsersData : Parameter set cannot be resolved using the specified named parameters.
At C:\TEMP\_101015_110059\try2.ps1:21 char:17
+ Backup-UsersData <<<<  'John'
    + CategoryInfo          : InvalidArgument: (:) [Backup-UsersData], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Backup-UsersData

在许多情况下,标准而非高级的混合参数函数可以:

function Backup-UsersData
(
    [string]$user,
    [object[]]$array,
    [switch]$all
)

    if ($user) 'user'
    elseif ($array) 'array'
    elseif ($all) 'all'
    else 'may be'


Backup-UsersData -user 'John'
Backup-UsersData -array 1, 2
Backup-UsersData -all
Backup-UsersData

但在这种情况下,您应该解决(或接受并忽略)歧义,例如决定做什么,如果说:

Backup-UsersData -user 'John' -array 1, 2 -all

【讨论】:

需要说明的是类函数可以重载。这与在其他语言中的完成方式类似,通过声明具有相同名称但参数类型不同的多个函数来完成。例如,具有函数[string] val([int] $i) return "Int: $i" [string] val([string] $s) return "String: $s" 的类将输出Int: 1 对应$t.val(1)String: abc 对应$t.val('abc')注意:我已验证此代码使用 PowerShell 5.1 和 7.1) 另外应该注意的是,Powershell(在 5.1 上,可能更早)可以并将单个值强制转换为 [Object[]] 参数:该函数将获取一个以原始对象作为其单个值的数组。这适用于任何类型,只要单个值可以强制转换为数组包含的类型(即"plop" 可以强制转换为[String[]],但不能转换为[Int32[]])。【参考方案2】:

这是 Roman 的答案的一个变体,我认为它更灵活一些:

function Backup

    [CmdletBinding(DefaultParameterSetName='Users')]
    Param (
        [parameter(mandatory=$true, ParameterSetName='Users', position=0, ValueFromPipeline=$true)][string[]]$User,
        [parameter(mandatory=$true, ParameterSetName='AllUsers')][switch]$All
    )

    Begin
    
        if ($All)  $User = @('User1', 'User2', 'User3') 
    

    Process
    
        foreach ($u in $User)
        
            echo "Backup $u"
        
    

【讨论】:

【参考方案3】:

1) 建立一个类...

class c1  
    [int]f1( [string]$x ) return 1  
    [int]f1( [int ]$x ) return 2 
    

1+) 如果您希望在不实例化的情况下调用它们,请使用静态方法...

class c1  
    static [int] f1( [string]$x ) return 1  
    static [int] f1( [int]$x ) return 2  
    

2) 调用类或对象中的方法...重载工作正常

$o1 = [c1]::new()
o1.f1( "abc" ) ~> returns 1
o1.f1( 123 )   ~> returns 2

-或-


[c1]::f1( "abc" ) ~> returns 1
[c1]::f1( 123 )   ~> returns 2

3) 如果(像我一样) 您希望将“重载函数”放置在库中... 这样您的用户就可以透明地使用它们... 来自代码或来自交互式命令行 (REPL)...

我能到的最接近的地方 “Powershell 中的重载函数” 是这样的:

function Alert-String()  [c1]::f1( "abc" ) 
function Alert-Strings() [c1]::f1( 123 ) 
function Alert-Stringn() [c1]::f1( 123 ) 

也许在 PS-Core v8 中??? ;-)

希望对你有帮助……

【讨论】:

【参考方案4】:

如果您使用 PSObject 而不是 Object 来定义参数类型,它应该可以工作。 例如Get-Control函数,知道如何根据类型字符串或模板进行重载,可以使用位置值调用:

    Get-Control "A-Name-Of-A-Control"
    Get-Control $template

要使重载工作,请按如下方式使用 PSObject:

Function Get-Control 
    Param(
        [Parameter(Mandatory=$False,ParameterSetName="ByTemplate",Position=0)]
        [PSObject]
        $Template,

        [Parameter(Mandatory=$False,ParameterSetName="ByName",Position=0)]        
        [String]
        $Name,

        [Parameter(Mandatory=$False)] 
        [Switch]
        $List
      ) 
   ... # remaining code removed for brevity

【讨论】:

以上是关于PowerShell 中的函数重载的主要内容,如果未能解决你的问题,请参考以下文章

类中的函数重载

“超出最大递归深度”,试图调用重载函数

类中的函数重载(二十三)

C++深度剖析学习总结 22 类中的函数重载

C++深度剖析学习总结 22 类中的函数重载

29 类中的函数重载