当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell 类:入门

作者:精品下载站 日期:2024-12-14 13:06:06 浏览:15 分类:玩电脑

PowerShell 类:入门


PowerShell 是一种面向对象的语言。当您运行命令时,请查看屏幕上的输出,这些是对象。物体并非凭空而来,而是凭空而来。开发人员创建它们,或者更具体地说,用类实例化它们。 PowerShell 类表示这些对象的定义或架构。

尽管您可能熟悉使用 New-Object 等命令以及使用 pscustomobject 类型加速器创建对象,但这些并不是“新”对象。这些方法生成的对象类型具有特定的类型。 PowerShell 类定义类型

在本教程中,您将学习如何开始使用 PowerShell 类。您将使用构造函数创建您的第一个类,学习如何从您的类创建对象,并使用属性和方法装饰您的类。

有关对象、属性和方法等术语的背景信息,请查看博客文章回归基础:了解 PowerShell 对象。

先决条件

创建您的第一个类和对象

在了解 PowerShell 类的详细信息之前,您应该首先创建一个简单的类。稍后您将了解更高级的主题。

创建你的第一个类感觉有点像创建一个函数。基本语法是相同的。类是根据函数的定义创建的。但与函数不同的是,第一行不是以 function 开头,后跟函数名称,而是以 class 开头,后跟对象类型的名称。

下面您将看到一个名为 student 的类的基本框架。

class student {

}

类的属性看起来像参数,参数是描述该类的属性。下面的示例显示了一个名为 student 的类,它具有两个属性: 名字姓氏

定义属性时,您应该始终定义一个类型,为属性值可以保存的内容设置特定的“架构”。在下面的示例中,两个属性都定义为字符串

您应该始终定义属性类型。稍后你就会明白为什么。

class student {
    [string]$FirstName
    [string]$LastName
}

定义类后,从中创建对象或实例化对象。有多种方法可以从类实例化对象;一种常见的方法是使用类型加速器,例如代表类的 [student],后跟每个类附带的默认方法 new()。

使用类型加速器快捷方式与使用 New-Object 命令创建对象相同。

New-Object -TypeName student

从该类创建对象后,即可为属性赋值。下面的示例为 FirstNameLastName 属性分配 TylerMuir 的值。

class student {
    [string]$FirstName
    [string]$LastName
}
$student1 = [student]::new()
$student1.FirstName = 'Tyler'
$student1.LastName = 'Muir'
$student1

创建对象并为属性赋值后,通过调用为对象分配的变量来检查对象,如下所示。

[玩转系统] PowerShell 类:入门

现在您已经从类创建了一个对象,就像 PowerShell 中的任何其他对象一样将该对象通过管道传输到 Get-Membercmdlet 来检查它。您可以在下面看到 $student1 变量中保存的对象的类型为 student

类名始终与对象类型相关。

请注意,Get-Member 返回四个方法和两个属性。这些属性可能看起来很熟悉,但方法肯定不熟悉。 PowerShell 默认添加某些方法,但您可以添加自己的方法,甚至修改默认方法。

[玩转系统] PowerShell 类:入门

创建方法

在上面的示例中,您看到了对象上的一些默认方法,但您很可能想要创建自己的方法。为此,您必须在类定义中定义一个或多个方法。

方法定义如下所示,其中的输出类型定义了从此方法返回的对象类型、方法的名称以及在脚本块内执行的代码。

[<output type>]<name>() {
	<code that runs when the method is executed>
}

请注意名称后面的括号 ()。您可以在此处定义方法参数(稍后介绍)。方法参数允许您更改方法的功能,就像使用函数参数一样。

如果您以前编写并运行过 PowerShell 函数,那么方法脚本块应该感觉很熟悉,但是您应该了解一些方法的特殊规则。

返回是强制性的

PowerShell 函数只需将对象放置在函数中的任何位置即可返回对象,如下例所示。

function foo {
	$object = Get-Service
	$object ## Just sending the object to the pipeline
}

但是,与函数不同的是,如果方法返回对象,则必须使用 return 构造,如下所示。

[string]GetName() {
	return 'foo'
}

使用 $this 变量

方法与函数的另一个区别是 $this 变量。 $this 变量在方法内部定义,引用当前对象的属性或其他方法。

下面是添加到 student 类中的名为 GetName() 的方法的示例,该方法连接 FirstNameLastName 的值 属性并返回它们。

class student {
    [string]$FirstName
    [string]$LastName
    
    [string]GetName() {
        return "$($this.FirstName) $($this.LastName)"
    }
}

现在您可以使用点表示法调用 GetName() 方法,如下所示。如果您之前为 FirstNameLastName 赋值,GetName() 将返回它们。

[玩转系统] PowerShell 类:入门

方法添加参数

在上面的示例中,当您运行 $student1.GetName() 行时,您按原样调用 GetName() 方法。在括号内,您可以像函数一样定义参数。

GetName() 方法仅返回为 FirstNameLastName 属性设置的任何值。但是,如果您希望有一个方法来设置属性,然后GetName()可以获取呢?在这种情况下,您需要定义方法参数。

通过在方法参数括号中包含一个或多个用逗号分隔的参数来定义方法参数,如下所示。

请注意 [void] 输出类型。每当方法不输出任何内容时,您就不需要 return 构造,并且应该将输出类型定义为 [void] 来告诉 PowerShell 该方法不返回任何内容.

[void]SetName([string]$Name) {

}

例如,SetName() 方法可能接受全名(名字和姓氏)。如果是这样,则在脚本块中,您可以拆分该字符串并以这种方式分配名字和姓氏。

通过在 student 类中插入 SetName() 方法,下面是现在的样子。

class student {
    [string]$FirstName
    [string]$LastName
    
    [string]GetName() {
        return "$($this.FirstName) $($this.LastName)"
    }
    
    [void]SetName([string]$Name) {
        $this.FirstName = ($Name -split ' ')[0]
        $this.LastName = ($Name -split ' ')[1]
    }
}

现在,您可以将全名作为参数传递给 SetName() 方法,该方法设置当前对象的 FirstNameLastName 属性。

[玩转系统] PowerShell 类:入门

重载方法

也许您想为一个方法定义不同的参数集。与函数和 cmdlet 中参数集的工作方式类似,您可以定义不同的参数“上下文”或方法签名。

也许您想通过将全名传递给 SetName() 方法或传递第一个和最后一个来设置 FirstNameLastName 参数分别命名。你不必选择;您可以使用方法签名来定义它们。

当您在一个类中定义多个方法签名时,这称为重载。

重复使用上一节中的示例,您可以为 SetName() 方法创建一个重载,以接受两个字符串而不是一个字符串。当您传入两个字符串而不是一个时,SetName() 方法假定第一个字符串是 FirstName,第二个字符串是 LastName 。有了这个重载,该类将如下所示。

class student {
    [string]$FirstName
    [string]$LastName
    
    [string]GetName() {
        return "$($this.FirstName) $($this.LastName)"
    }
    
    [void]SetName([string]$Name) {
        $this.FirstName = ($Name -split ' ')[0]
        $this.LastName = ($Name -split ' ')[1]
    }
    
    [void]SetName([string]$FirstName,[string]$LastName) {
        $this.FirstName = $FirstName
        $this.LastName = $LastName
    }
}

[玩转系统] PowerShell 类:入门

类构造函数

每当您使用 new() 方法或其他方式实例化对象时,您都可以告诉 PowerShell 运行一些称为构造函数的用户定义代码。构造函数类似于方法,但它们在 PowerShell 实例化对象时自动运行。

每个类都有一个默认构造函数。这个默认构造函数没有做太多事情;它只负责实例化对象。您可以通过查看 New 方法的输出来查看默认构造函数。您可以在下面看到这一行返回一个 new() 方法。

[student]::New

[玩转系统] PowerShell 类:入门

构造函数重载

也许您希望在创建对象后立即为 FirstNameLastName 属性设置一个值,而不是使用典型的点表示法。在这种情况下,您可以创建一个带有参数的构造函数,然后调用 SetName()

下面是 student 类的构造函数示例。请注意,构造函数没有特定名称或以输出类型开头。构造函数始终使用与类相同的名称。

在构造函数中调用现有方法允许我们重用已经编写的方法来处理设置变量。

student([string]$Name) {
	$this.SetName($Name)
}

下面您将看到该构造函数已添加到 student 类中。

class student {
    [string]$FirstName
    [string]$LastName
    
    student([string]$Name) {
        $this.SetName($Name)
    }

    [string]GetName() {
        return "$($this.FirstName) $($this.LastName)"
    }
    
    [void]SetName([string]$Name) {
        $this.FirstName = ($Name -split ' ')[0]
        $this.LastName = ($Name -split ' ')[1]
    }

    [void]SetName([string]$FirstName,[string]$LastName) {
        $this.FirstName = $FirstName
        $this.LastName = $LastName
    }
}

当您实例化一个新的 student 对象并传入字符串参数时,对象属性将立即具有预期值。

[玩转系统] PowerShell 类:入门

现在,您可以使用 [student]::New 再次看到重载的构造函数。现在请注意,使用 Name 参数定义的新重载构造函数。

[玩转系统] PowerShell 类:入门

定义默认和重载的构造函数

现在您的 student 类上已经有了重载的构造函数,PowerShell 会覆盖默认构造函数。但是,您可以通过手动创建一个不带参数的值来取回它。

student() {}

您可以在下面的 student 类中看到它的样子。

class student {
    [string]$FirstName
    [string]$LastName

    student([string]$Name) {
        $this.SetName($Name)
    }

    student() {}

    [void]SetName([string]$Name) {
        $this.FirstName = ($Name -split ' ')[0]
        $this.LastName = ($Name -split ' ')[1]
    }
}

现在再次检查构造函数。现在您将看到两个构造函数都出现了。

[student]::New

[玩转系统] PowerShell 类:入门

类继承

与所有其他面向对象的语言一样,您可以使用多个类分层构建 PowerShell 类。每个类都可以有“父”类和“子”类,这些类从不太具体、更通用的目的开始并增加特异性。

例如,我们的 student 类代表一名大学生(儿童/特定学生)。该大学生是一个人(家长/通用)。这两个概念相互关联并形成一个层次结构。

子类可以继承父类,这意味着它可以保存通过父类定义的所有属性和方法(成员)。我们知道 person 类可能具有 eye_colorheightweight 等属性,并且可能还有一个名为 SetHeight()。

如果学生是一个人,那么该学生仍然具有那些属性和方法。在 student 类上实现 person 类已有的相同成员会重复工作。您可以定义类继承,以自动在 student 类上定义 person 类的所有成员。

如果现在这还没有意义,那么当我们进行演示时就会明白了。

类继承演示

首先,复制您之前创建的 student 类,删除构造函数并将其重命名为 person 类。你的 person 类应该像下面的类一样。

当然,学生有名字和姓氏,但通过将其标记为人可以更准确地描述班级。当创建像这样的更“通用”类时,您可以从中创建更具体的“子”类。

class person {
    [string]$FirstName
    [string]$LastName
    
    [string]GetName() {
        return "$($this.FirstName) $($this.LastName)"
    }
    
    [void]SetName([string]$Name) {
        $this.FirstName = ($Name -split ' ')[0]
        $this.LastName = ($Name -split ' ')[1]
    }

    [void]SetName([string]$FirstName,[string]$LastName) {
        $this.FirstName = $FirstName
        $this.LastName = $LastName
    }
}

现在,创建几个代表一个人但具有更具体角色的类。例如,在下面的代码片段中,您现在有一个 teacherstudent 类。

class teacher {
    [int]$EmployeeId
}

class student {
    [int]$StudentId
}

按原样,teacherstudent 类与 person 类是互斥的。他们没有关系,但不能继承 person 类的任何类成员。让我们改变这一点。

现在,通过将 teacherstudent 类定义为具有继承性的 person 类的“子”类来定义该层次结构。您可以通过在类名后附加冒号 (:) 和父类的名称来定义继承,如下所示。

class teacher : person {
    [int]$EmployeeId
}

class student : person {
    [int]$StudentId
}

您的整个类脚本现在应如下所示:

class person {
    [string]$FirstName
    [string]$LastName
    
    [string]GetName() {
        return "$($this.FirstName) $($this.LastName)"
    }
    
    [void]SetName([string]$Name) {
        $this.FirstName = ($Name -split ' ')[0]
        $this.LastName = ($Name -split ' ')[1]
    }

    [void]SetName([string]$FirstName,[string]$LastName) {
        $this.FirstName = $FirstName
        $this.LastName = $LastName
    }
}

class teacher : person {
    [int]$EmployeeId
}

class student : person {
    [int]$StudentId
}

此时,当您从 teacherstudent 类实例化对象时,这两个类将具有与 person 类相同的成员。

[玩转系统] PowerShell 类:入门

使用构造函数继承

正如您在上面看到的,类方法是通过类继承来继承的。这种行为可能会让您认为构造函数会遵循相同的逻辑,但您错了。构造函数不是继承的,所有子类的构造函数必须在每个子类中单独定义。

例如,也许您刚刚为 person 类定义了一个重载构造函数,但没有为 teacher 类定义构造函数,如下所示。

class person {
    [string]hidden $FirstName
    [string]$LastName
    
    [string]GetName() {
        return "$($this.FirstName) $($this.LastName)"
    }
    
    [void]SetName([string]$Name) {
        $this.FirstName = ($Name -split ' ')[0]
        $this.LastName = ($Name -split ' ')[1]
    }

    [void]SetName([string]$FirstName,[string]$LastName) {
        $this.FirstName = $FirstName
        $this.LastName = $LastName
    }

		person([string]$Name) {
			$this.SetName($Name)
		}
}

然后,您定义一个子类,例如,teacher,并尝试创建一个不带参数的对象,如下所示。请注意,PowerShell 返回错误,因为在 teacher 类内部未定义无参数构造函数。

[玩转系统] PowerShell 类:入门

如果您仅将其用作模板,则子类中不需要构造函数。或者,如果您想使用父类作为其自己的独立类,并且作为父类,您可以包含构造函数。但你必须确保父类有一个与子类中的构造函数相匹配的构造函数。

类成员属性

就像 PowerShell 命令参数一样,类可以具有成员属性。这些属性修改每个成员的行为。

隐藏成员

如果您仅将类成员用于内部目的并且不希望用户读取或写入它,则可以将成员设置为隐藏。例如,也许您有一个仅由其他方法使用的方法。无需向用户公开该方法。

要定义隐藏成员,请使用 hidden 属性,如下所示。

class teacher {
    [int]hidden $EmployeeId
}

现在,当您使用 Get-Member 检查所有对象成员时,该属性不会显示。

[玩转系统] PowerShell 类:入门

将类成员设置为隐藏不会限制对该值的访问;它只是将其隐藏起来。您不应隐藏属性来存储敏感数据。

静态成员

回忆一下早些时候;本教程使用术语“实例化”来描述从类创建对象。当您实例化一个对象时,该对象将采用该类定义的所有属性和方法。但情况并非总是如此。

有时,您不需要实例化整个对象的开销。相反,您需要快速引用单个类成员。在这种情况下,您可以将类成员设置为静态

正如 hidden 属性一样,使用 static 关键字将类成员定义为静态,如下所示。

class student {
	[int]static $MaxClassCount = 7
}

与典型的类成员不同,PowerShell 不会从静态类成员创建属性和方法。当您将类成员定义为静态成员(如隐藏成员)时,当您使用 Get-Member 时,该成员不会显示。

[玩转系统] PowerShell 类:入门

例如,您可能希望将大学班级名称与 student 班级相关联,并定义学生可以参加的大学班级的最大数量。为此,您需要创建一个 Classes 数组成员和 MaxClassCount 成员。

由于用户很少需要更改 MaxClassCount 成员,因此您决定将其定义为静态。

最后,您创建一个 AddClass() 方法来将课程添加到学生的课程表中,但前提是它小于该 MaxClassCount

class student {
    [string[]]$Classes = @()
    [int]static $MaxClassCount = 7
    
    [void]AddClass ([string]$Name) {
        if ($this.Classes.Count -lt [student]::MaxClassCount) {
            $this.Classes += $Name
        }
    }
}

现在,当您尝试创建新的 student 对象并为其分配过多的大学课程时,PowerShell 将仅分配最大数量,即 7。

$student1 = [student]::new()
'PE','English','Math','History','Computer Science','French','Wood Working','Cooking' | ForEach-Object {
	$student1.AddClass($_)
}
$student1.Classes

[玩转系统] PowerShell 类:入门

您可以随时更改静态成员值。例如,如果您希望将 MaxClassCount 成员设置为 5 而不是 7,则可以使用 [student]::MaxClassCount=5 更改该值。更改该值不会追溯删除超出本示例中限制的类。

结论

PowerShell 类模糊了脚本语言和编程语言之间的界限。类是定义对象关系、添加与对象交互和格式化对象的方式的好方法,而这些方式通常只能通过编写专门的函数来实现。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯