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 中的函数重载的主要内容,如果未能解决你的问题,请参考以下文章