# Visual Basic 中的面向对象编程 II
> 原文: [https://zetcode.com/lang/visualbasic/oopii/](https://zetcode.com/lang/visualbasic/oopii/)
在 Visual Basic 教程的这一章中,我们将继续以 Visual Basic 语言描述 OOP。
## 接口
遥控器是观众和电视之间的接口。 它是此电子设备的接口。 外交礼仪指导外交领域的所有活动。 道路规则是驾车者,骑自行车者和行人必须遵守的规则。 编程中的接口类似于前面的示例。
接口是:
* API
* 合约
对象通过这些方法与外界交互。 实际的实现对程序员而言并不重要,或者也可能是秘密的。 公司可能会出售图书馆,但它不想透露实际的实现情况。 程序员可能会在 GUI 工具箱的窗口中调用`Maximize`方法,但对如何实现此方法一无所知。 从这个角度来看,接口是一种方法,通过这些方法,对象可以与外界交互,而不会过多地暴露其内部工作原理。
从第二个角度来看,接口就是契约。 如果达成协议,则必须遵循。 它们用于设计应用的架构。 他们帮助组织代码。
接口是完全抽象的类型。 它们使用`Interface`关键字声明。 接口只能具有方法签名和常量。 接口中声明的所有方法签名必须是公共的。 他们不能具有完全实现的方法,也不能具有成员字段。 Visual Basic 类可以实现任何数量的接口。 一个接口还可以扩展任何数量的接口。 实现接口的类必须实现接口的所有方法签名。
接口用于模拟多重继承。 Visual Basic 类只能从一个类继承。 Visual Basic 类可以实现多个接口。 使用接口的多重继承与继承方法和变量无关。 它是关于继承想法或合同的,这些想法或合同由接口描述。
接口和抽象类之间有一个重要的区别。 抽象类为继承层次结构中相关的类提供部分实现。 另一方面,可以通过彼此不相关的类来实现接口。 例如,我们有两个按钮。 经典按钮和圆形按钮。 两者都继承自抽象按钮类,该类为所有按钮提供了一些通用功能。 实现类是相关的,因为它们都是按钮。 另一个示例可能具有类`Database`和`SignIn`。 它们彼此无关。 我们可以应用`ILoggable`接口,该接口将迫使他们创建执行日志记录的方法。
```vb
Option Strict On
Module Example
Interface IInfo
Sub DoInform()
End Interface
Class Some
Implements IInfo
Sub DoInform() Implements IInfo.DoInform
Console.WriteLine("This is Some Class")
End Sub
End Class
Sub Main()
Dim sm As New Some
sm.DoInform()
End Sub
End Module
```
这是一个演示接口的简单 Visual Basic 程序。
```vb
Interface IInfo
Sub DoInform()
End Interface
```
这是接口`IInfo`。 它具有`DoInform()`方法签名。
```vb
Class Some
Implements IInfo
```
我们使用`Implements`从接口实现。
```vb
Sub DoInform() Implements IInfo.DoInform
Console.WriteLine("This is Some Class")
End Sub
```
该类提供了`DoInform()`方法的实现。 `Implements`关键字明确指定了我们正在实现的方法签名。
下一个示例显示了一个类如何实现多个接口。
```vb
Option Strict On
Module Example
Interface Device
Sub SwitchOn()
Sub SwitchOff()
End Interface
Interface Volume
Sub VolumeUp()
Sub VolumeDown()
End Interface
Interface Pluggable
Sub PlugIn()
Sub PlugOff()
End Interface
Class CellPhone
Implements Device, Volume, Pluggable
Public Sub SwitchOn() Implements Device.SwitchOn
Console.WriteLine("Switching on")
End Sub
Public Sub SwitchOff() Implements Device.SwitchOff
Console.WriteLine("Switching on")
End Sub
Public Sub VolumeUp() Implements Volume.VolumeUp
Console.WriteLine("Volume up")
End Sub
Public Sub VolumeDown() Implements Volume.VolumeDown
Console.WriteLine("Volume down")
End Sub
Public Sub PlugIn() Implements Pluggable.PlugIn
Console.WriteLine("Plugging In")
End Sub
Public Sub PlugOff() Implements Pluggable.PlugOff
Console.WriteLine("Plugging Off")
End Sub
End Class
Sub Main()
Dim o As New CellPhone
o.SwitchOn()
o.VolumeUp()
o.PlugIn()
End Sub
End Module
```
我们有一个`CellPhone`类,它从三个接口继承。
```vb
Class CellPhone
Implements Device, Volume, Pluggable
```
该类实现所有三个接口,并用逗号分隔。 `CellPhone`类必须实现来自所有三个接口的所有方法签名。
```vb
$ ./interface.exe
Switching on
Volume up
Plugging In
```
运行程序。
下一个示例显示接口如何从多个其他接口继承。
```vb
Option Strict On
Module Example
Interface IInfo
Sub DoInform()
End Interface
Interface IVersion
Sub GetVersion()
End Interface
Interface ILog
Inherits IInfo, IVersion
Sub DoLog
End Interface
Class DBConnect
Implements ILog
Public Sub DoInform() Implements IInfo.DoInform
Console.WriteLine("This is DBConnect class")
End Sub
Public Sub GetVersion() Implements IVersion.GetVersion
Console.WriteLine("Version 1.02")
End Sub
Public Sub DoLog() Implements ILog.DoLog
Console.WriteLine("Logging")
End Sub
Public Sub Connect()
Console.WriteLine("Connecting to the database")
End Sub
End Class
Sub Main()
Dim db As New DBConnect
db.DoInform()
db.GetVersion()
db.DoLog()
db.Connect()
End Sub
End Module
```
我们定义了三个接口。 我们可以按层次组织接口。
```vb
Interface ILog
Inherits IInfo, IVersion
```
`ILog`接口继承自其他两个接口。
```vb
Public Sub DoInform() Implements IInfo.DoInform
Console.WriteLine("This is DBConnect class")
End Sub
```
`DBConnect`类实现`DoInform()`方法。 该方法由该类实现的`ILog`接口继承。
```vb
$ ./interface2.exe
This is DBConnect class
Version 1.02
Logging
Connecting to the database
```
输出。
## 多态
多态是以不同方式将运算符或函数用于不同数据输入的过程。 实际上,多态意味着如果类`B`从类`A`继承,则不必继承关于类`A`的所有内容; 它可以完成`A`类所做的某些事情。 (维基百科)
通常,多态是以不同形式出现的能力。 从技术上讲,它是重新定义派生类的方法的能力。 多态与将特定实现应用于接口或更通用的基类有关。
多态是重新定义派生类的方法的能力。
```vb
Option Strict On
Module Example
MustInherit Class Shape
Protected x As Integer
Protected y As Integer
Public MustOverride Function Area() As Integer
End Class
Class Rectangle
Inherits Shape
Sub New(ByVal x As Integer, ByVal y As Integer)
Me.x = x
Me.y = y
End Sub
Public Overrides Function Area() As Integer
Return Me.x * Me.y
End Function
End Class
Class Square
Inherits Shape
Sub New(ByVal x As Integer)
Me.x = x
End Sub
Public Overrides Function Area() As Integer
Return Me.x * Me.x
End Function
End Class
Sub Main()
Dim shapes() As Shape = { New Square(5), _
New Rectangle(9, 4), New Square(12) }
For Each shape As Shape In shapes
Console.WriteLine(shape.Area())
Next
End Sub
End Module
```
在上面的程序中,我们有一个抽象的`Shape`类。 该类变形为两个后代类,即`Rectangle`和`Square`。 两者都提供了自己的`Area()`方法的实现。 多态为 OOP 系统带来了灵活性和可伸缩性。
```vb
Public Overrides Function Area() As Integer
Return Me.x * Me.y
End Function
...
Public Overrides Function Area() As Integer
Return Me.x * Me.x
End Function
```
`Rectangle`和`Square`类具有`Area`方法的自己的实现。
```vb
Dim shapes() As Shape = { New Square(5), _
New Rectangle(9, 4), New Square(12) }
```
我们创建三个形状的数组。
```vb
For Each shape As Shape In shapes
Console.WriteLine(shape.Area())
Next
```
我们遍历每个形状并在其上调用`Area`方法。 编译器为每种形状调用正确的方法。 这就是多态的本质。
## `NotOverridable`,`NotInheritable`
`NotOverridable`方法不能被覆盖,`NotInheritable`类不能从中继承。 这些关键字与应用设计有关。 我们不应从某些类继承,并且不应重写某些方法。
```vb
Option Strict On
Module Example
Class Base
Public NotOverridable Sub Say()
Console.WriteLine("Base class")
End Sub
End Class
Class Derived
Inherits Base
Public Overrides Sub Say()
Console.WriteLine("Derived class")
End Sub
End Class
Sub Main()
Dim o As Base = New Derived
o.Say()
End Sub
End Module
```
该程序将无法编译。 我们收到错误消息`"Public Overrides Sub Say()"`无法覆盖`"Public NotOverridable Sub Say()"`,因为它被声明为`"NotOverridable"`。
```vb
Option Strict On
Module Example
NotInheritable Class Math
Public Shared Function getPI() As Single
Return 3.141592
End Function
End Class
Class DerivedMath
Inherits Math
Public Sub Say()
Console.WriteLine("DerivedMath class")
End Sub
End Class
Sub Main()
Dim o As DerivedMath = New DerivedMath
o.Say()
End Sub
End Module
```
在上面的程序中,我们有一个原型基础`Math`类。 该类的唯一目的是为程序员提供一些有用的方法和常量。 (出于简单起见,在我们的案例中,我们只有一种方法。)它不是从继承而创建的。 为了防止不知情的其他程序员从此类中派生,创建者创建了`NotInheritable`类。 如果尝试编译该程序,则会出现以下错误:'DerivedMath'无法从类'Math'继承,因为'Math'被声明为'NotInheritable'。
## 深拷贝与浅拷贝
数据复制是编程中的重要任务。 对象是 OOP 中的复合数据类型。 对象中的成员字段可以按值或按引用存储。 可以以两种方式执行复制。
浅表副本将所有值和引用复制到新实例中。 引用所指向的数据不会被复制; 仅指针被复制。 新的引用指向原始对象。 对引用成员的任何更改都会影响两个对象。
深层副本将所有值复制到新实例中。 如果成员存储为引用,则深层副本将对正在引用的数据执行深层副本。 创建一个引用对象的新副本。 并存储指向新创建对象的指针。 对这些引用对象的任何更改都不会影响该对象的其他副本。 深拷贝是完全复制的对象。
如果成员字段是值类型,则将对该字段进行逐位复制。 如果该字段是引用类型,则复制引用,但不是复制引用的对象。 因此,原始对象中的引用和克隆对象中的引用指向同一对象。 (来自 programmingcorner.blogspot.com 的明确解释)
接下来的两个示例将对对象执行浅表复制和深表复制。
```vb
Option Strict On
Module Example
Class Color
Public red as Byte
Public green as Byte
Public blue as Byte
Sub New(red As Byte, green As Byte, _
blue As Byte)
Me.red = red
Me.green = green
Me.blue = blue
End Sub
End Class
Class MyObject
Implements ICloneable
Public Id As Integer
Public Size As String
Public Col As Color
Sub New(Id As Integer, Size As String, _
Col As Color)
Me.Id = Id
Me.Size = Size
Me.Col = Col
End Sub
Public Function Clone() As Object _
Implements ICloneable.Clone
Return New MyObject(Me.Id, Me.Size, Me.Col)
End Function
Public Overrides Function ToString() As String
Dim s As String
s = String.Format("Id: {0}, Size: {1}, Color:({2}, {3}, {4})", _
Me.Id, Me.Size, Me.Col.red, Me.Col.green, Me.Col.blue)
Return s
End Function
End Class
Sub Main()
Dim col As New Color(23, 42, 223)
Dim obj1 As New MyObject(23, "small", col)
Dim obj2 As MyObject
obj2 = CType(obj1.Clone(), MyObject)
obj2.Id += 1
obj2.Size = "big"
obj2.Col.red = 255
Console.WriteLine(obj1)
Console.WriteLine(obj2)
End Sub
End Module
```
这是一个浅表副本的示例。 我们定义了两个自定义对象:`MyObject`和`Color`。 `MyObject`对象将具有对`Color`对象的引用。
```vb
Class MyObject
Implements ICloneable
```
我们应该为要克隆的对象实现`ICloneable`接口。
```vb
Public Function Clone() As Object _
Implements ICloneable.Clone
Return New MyObject(Me.Id, Me.Size, Me.Col)
End Function
```
`ICloneable`接口迫使我们创建`Clone()`方法。 此方法返回具有复制值的新对象。
```vb
Dim col As New Color(23, 42, 223)
```
我们创建`Color`对象的实例。
```vb
Dim obj1 As New MyObject(23, "small", col)
```
创建`MyObject`对象的实例。 它将`Color`对象的实例传递给其构造器。
```vb
obj2 = CType(obj1.Clone(), MyObject)
```
我们创建`obj1`对象的浅表副本,并将其分配给`obj2`变量。 `Clone()`方法返回`Object`,我们期望`MyObject`。 这就是我们进行显式转换的原因。
```vb
obj2.Id += 1
obj2.Size = "big"
obj2.Col.red = 255
```
在这里,我们修改复制对象的成员字段。 我们增加`Id`,将`Size`更改为`"big"`,然后更改颜色对象的红色部分。
```vb
Console.WriteLine(obj1)
Console.WriteLine(obj2)
```
`Console.WriteLine()`方法调用`obj2`对象的`ToString()`方法,该方法返回对象的字符串表示形式。
```vb
Id: 23, Size: small, Color:(255, 42, 223)
Id: 24, Size: big, Color:(255, 42, 223)
```
我们可以看到 ID 分别为 23 和 24。大小不同。 `small`和`big`。 但是,这两个实例的颜色对象的红色部分相同:255。更改克隆对象的成员值(`Id`,`Size`)不会影响原始对象。 更改引用对象(`Col`)的成员也影响了原始对象。 换句话说,两个对象都引用内存中的同一颜色对象。
要更改此行为,我们接下来将做一个深层复制。
```vb
Option Strict On
Module Example
Class Color
Implements ICloneable
Public Red as Byte
Public Green as Byte
Public Blue as Byte
Sub New(Red As Byte, Green As Byte, _
Blue As Byte)
Me.Red = Red
Me.Green = Green
Me.Blue = Blue
End Sub
Public Function Clone() As Object _
Implements ICloneable.Clone
Return New Color(Me.Red, Me.Green, Me.Blue)
End Function
End Class
Class MyObject
Implements ICloneable
Public Id As Integer
Public Size As String
Public Col As Color
Sub New(Id As Integer, Size As String, _
Col As Color)
Me.Id = Id
Me.Size = Size
Me.Col = Col
End Sub
Public Function Clone() As Object _
Implements ICloneable.Clone
Return New MyObject(Me.Id, Me.Size, CType(Me.Col.Clone(), Color))
End Function
Public Overrides Function ToString() As String
Dim s As String
s = String.Format("Id: {0}, Size: {1}, Color:({2}, {3}, {4})", _
Me.Id, Me.Size, Me.Col.Red, Me.Col.Green, Me.Col.Blue)
Return s
End Function
End Class
Sub Main()
Dim col As New Color(23, 42, 223)
Dim obj1 As New MyObject(23, "small", col)
Dim obj2 As MyObject
obj2 = CType(obj1.Clone(), MyObject)
obj2.Id += 1
obj2.Size = "big"
obj2.Col.Red = 255
Console.WriteLine(obj1)
Console.WriteLine(obj2)
End Sub
End Module
```
在此程序中,我们对对象执行深层复制。
```vb
Class Color
Implements ICloneable
```
现在`Color`类实现了`ICloneable`接口。
```vb
Public Function Clone() As Object _
Implements ICloneable.Clone
Return New Color(Me.Red, Me.Green, Me.Blue)
End Function
```
我们也为`Color`类提供了`Clone()`方法。 这有助于创建引用对象的副本。
```vb
Public Function Clone() As Object _
Implements ICloneable.Clone
Return New MyObject(Me.Id, Me.Size, CType(Me.Col.Clone(), Color))
End Function
```
现在,当我们克隆`MyObject`时,我们以`Col`引用类型调用`Clone()`方法。 这样,我们也可以获得颜色值的副本。
```vb
$ ./deepcopy.exe
Id: 23, Size: small, Color:(23, 42, 223)
Id: 24, Size: big, Color:(255, 42, 223)
```
现在,引用的`Color`对象的红色部分不相同。 原始对象保留了其先前的 23 值。
## 异常
异常是为处理异常的发生而设计的,这些特殊情况会改变程序执行的正常流程。 引发或引发异常。
在执行应用期间,许多事情可能出错。 磁盘可能已满,我们无法保存文件。 互联网连接可能断开,我们的应用尝试连接到站点。 所有这些都可能导致我们的应用崩溃。 为避免发生这种情况,我们必须应对可能发生的所有可能的错误。 为此,我们可以使用异常处理。
`Try`,`Catch`和`Finally`关键字用于处理异常。
```vb
Option Strict On
Module Example
Sub Main()
Dim x As Integer = 100
Dim y As Integer = 0
Dim z As Double
Try
z = x \ y
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
End Module
```
在上面的程序中,我们有意将数字除以零。 这会导致错误。
```vb
Try
z = x \ y
...
End Try
```
容易出错的语句放在`Try`关键字之后。
```vb
Catch e As Exception
Console.WriteLine(e.Message)
...
```
异常类型跟随`Catch`关键字。 在我们的例子中,我们有一个通用的`Exception`,它将捕获任何类型的异常。 有一些通用的异常,还有一些更具体的异常。 发生错误时,将执行`Catch`关键字后面的语句。 发生异常时,将创建一个异常对象。 从该对象中,我们获得`Message`属性并将其打印到控制台。
当前上下文中任何未捕获的异常都会传播到更高的上下文,并寻找适当的 `catch`块来处理它。 如果找不到任何合适的`catch`块,则 .NET 运行时的默认机制将终止整个程序的执行。
```vb
Option Strict On
Module Example
Sub Main()
Dim z As Double
Dim x As Integer = 100
Dim y As Integer = 0
z = x \ y
End Sub
End Module
```
在此程序中,我们除以零。 我们没有自定义异常处理。 在 Visual Basic 2008 Express 上,我们收到以下错误消息:“未处理的异常:`System.DivideByZeroException`:试图除以零。”。
```vb
Option Strict On
Imports System.IO
Module Example
Dim fs As FileStream
Sub Main()
Try
fs = File.Open("file", FileMode.OpenOrCreate)
Console.WriteLine(fs.Length)
Catch e As IOException
Console.WriteLine("IO Error")
Console.WriteLine(e.Message)
Finally
Console.WriteLine("Finally")
If fs.CanRead = True Then
fs.Close()
End If
End Try
End Sub
End Module
```
始终执行`Finally`关键字之后的语句。 它通常用于清理任务,例如关闭文件或清除缓冲区。
```vb
Catch e As IOException
Console.WriteLine("IO Error")
Console.WriteLine(e.Message)
```
在这种情况下,我们捕获了特定的`IOException`异常。
```vb
Finally
Console.WriteLine("Finally")
If fs.CanRead = True Then
fs.Close()
End If
```
这些行确保关闭文件处理器。
```vb
Option Strict On
Module Example
Sub Main()
Dim x As Integer
Dim y As Integer
Dim z As Double
Try
Console.Write("Enter first number: ")
x = Convert.ToInt32(Console.ReadLine())
Console.Write("Enter second number: ")
y = Convert.ToInt32(Console.ReadLine())
z = x / y
Console.WriteLine("Result: {0:D} / {1:D} = {2:D}", x, y, z)
Catch e As DivideByZeroException
Console.WriteLine("Cannot divide by zero.")
Catch e As FormatException
Console.WriteLine("Wrong format of number.")
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
End Module
```
在此示例中,我们捕获了各种异常。 请注意,更具体的异常应先于一般的异常。 我们从控制台读取两个数字,并检查零除错误和数字格式错误。
```vb
$ ./passing.exe
Enter first number: et
Wrong format of number.
```
运行示例。
```vb
Option Strict On
Module Example
Class BigValueException
Inherits Exception
Sub New(ByVal msg As String)
MyBase.New(msg)
End Sub
End Class
Sub Main()
Dim x As Integer = 340004
Const LIMIT As Integer = 333
Try
If (x > LIMIT) Then
Throw New BigValueException("Exceeded the maximum value")
End If
Catch e As BigValueException
Console.WriteLine(e.Message)
End Try
End Sub
End Module
```
假设我们处于无法处理大量数字的情况。
```vb
Class BigValueException
Inherits Exception
```
我们有一个`BigValueException`类。 该类派生自内置的`Exception`类。
```vb
Dim Const LIMIT As Integer = 333
```
大于此常数的数字在我们的程序中被视为`big`。
```vb
Sub New(ByVal msg As String)
MyBase.New(msg)
End Sub
```
在构造器内部,我们称为父级的构造器。 我们将消息传递给父级。
```vb
If (x > LIMIT) Then
Throw New BigValueException("Exceeded the maximum value")
End If
```
如果该值大于限制,则抛出自定义异常。 我们给异常消息`"Exceeded the maximum value"`。
```vb
Catch e As BigValueException
Console.WriteLine(e.Message)
```
我们捕获到异常并将其消息打印到控制台。
## 属性
属性是特殊的类成员。 我们使用预定义的设置和获取方法来访问和修改它们。 属性读取和写入会转换为获取和设置方法调用。 与使用自定义方法调用(例如`object.GetName()`)相比,使用字段符号(例如`object.Name`)访问变量更容易。 但是,就属性而言,我们仍然具有封装和信息隐藏的优势。
```vb
Option Strict On
Module Example
Class Person
Private _name As String
Public Property Name() As String
Get
Return _name
End Get
Set (Byval Value As String)
_name = Value
End Set
End Property
End Class
Sub Main()
Dim p as New Person
p.Name = "Jane"
Console.WriteLine(p.Name())
End Sub
End Module
```
我们有一个带有一个属性的简单`Person`类。
```vb
Public Property Name() As String
...
End Property
```
我们使用`Property`关键字在 Visual Basic 中创建属性。
```vb
Get
Return _name
End Get
```
我们使用预定义的`Get`关键字为`_name`字段创建访问器方法。
```vb
Set (Byval Value As String)
_name = Value
End Set
```
类似地,`Set`关键字为`_name`字段创建一个修改器方法。
```vb
Dim p as New Person
p.Name = "Jane"
Console.WriteLine(p.Name())
```
我们创建`Person`类的实例。 我们使用字段符号访问成员字段。
```vb
$ ./properties.exe
Jane
```
这是该计划的结果。
## 委托
委托是 .NET Framework 使用的一种类型安全的函数指针。 委托通常用于实现回调和事件监听器。
```vb
Option Strict On
Module Example
Public Delegate Sub NameDelegate(ByVal msg As String)
Class Person
Private FirstName As String
Private SecondName As String
Sub New(First As String, Second As String)
Me.FirstName = First
Me.SecondName = Second
End Sub
Public Sub ShowFirstName(msg As String)
Console.WriteLine(msg & Me.FirstName)
End Sub
Public Sub ShowSecondName(msg As String)
Console.WriteLine(msg & Me.SecondName)
End Sub
End Class
Sub Main()
Dim nDelegate As NameDelegate
Dim per As New Person("Fabius", "Maximus")
nDelegate = AddressOf per.ShowFirstName
nDelegate("Call 1: ")
nDelegate = AddressOf per.ShowSecondName
nDelegate("Call 2: ")
End Sub
End Module
```
在此示例中,我们只有一名委托。 该委托用于指向`Person`类的两个方法。 方法与委托一起调用。
```vb
Public Delegate Sub NameDelegate(ByVal msg As String)
```
使用`Delegate`关键字创建委托。 委托签名必须与委托调用的方法的签名匹配。
```vb
Dim nDelegate As NameDelegate
```
在这里,我们创建一个自定义委托类型的变量。
```vb
nDelegate = AddressOf per.ShowFirstName
nDelegate("Call 1: ")
```
`AddressOf`运算符用于获取对`ShowFirstName(`方法的引用。 现在我们指向该方法,我们可以通过委托来调用它。
```vb
$ ./simpledelegate.exe
Call 1: Fabius
Call 2: Maximus
```
这两个名称都是通过委托打印的。
## 事件
事件是由某些操作触发的消息。 点击按钮或时钟的滴答声就是这样的动作。 触发事件的对象称为发送者,而接收事件的对象称为接收者。
```vb
Option Strict On
Module Example
Public Event ValueFive()
Dim Random As Integer
Public Sub Main()
AddHandler ValueFive, AddressOf OnFiveEvent
For i As Integer = 0 To 10
Randomize()
Random = CInt(Rnd() * 7)
Console.WriteLine(Random)
If Random = 5 Then
RaiseEvent ValueFive()
End If
Next
End Sub
Public Sub OnFiveEvent()
Console.WriteLine("Five Event occured")
End Sub
End Module
```
我们有一个简单的示例,可以在其中创建和启动事件。 生成一个随机数。 如果数字等于 5,则会生成`FiveEvent`事件。
```vb
Public Event ValueFive()
```
使用`Event`关键字声明事件。
```vb
AddHandler ValueFive, AddressOf OnFiveEvent
```
在这里,我们将名为`ValueFive()`的事件插入`OnFiveEvent()`子例程。 换句话说,如果触发了`ValueFive`事件,则将执行`OnFiveEvent()`子例程。
```vb
If Random = 5 Then
RaiseEvent ValueFive()
End If
```
当随机数等于 5 时,我们引发`ValueFive`事件。 我们使用`RaiseEvent`关键字。
```vb
$ ./event.exe
0
1
5
Five Event occured
2
5
Five Event occured
6
7
6
3
3
1
```
该程序的结果可能如下所示。
接下来,我们有一个更复杂的示例。
```vb
Option Strict On
Namespace EventSample
Public Class FiveEventArgs
Inherits EventArgs
Public Count As Integer
Public Time As Date
Public Sub New(ByVal Count As Integer, ByVal Time As Date)
Me.Count = Count
Me.Time = Time
End Sub
End Class
Public Class Five
Private Count As Integer = 0
Public Sub OnFiveEvent(ByVal source As Object, _
ByVal e As FiveEventArgs)
Console.WriteLine("Five event {0} occured at {1}", _
e.Count, e.Time)
End Sub
End Class
Public Class RandomGenerator
Public Event ValueFive(ByVal source As Object, _
ByVal e As FiveEventArgs)
Public Sub Generate()
Dim Count As Integer = 0
Dim args As FiveEventArgs
For i As Byte = 0 To 10
Dim Random As Integer
Randomize()
Random = CInt(Rnd * 6)
Console.WriteLine(Random)
If Random = 5 Then
Count += 1
args = New FiveEventArgs(Count, Now)
RaiseEvent ValueFive(Me, args)
End If
Next
End Sub
End Class
Public Class Example
Public Shared Sub Main()
Dim five As New Five
Dim gen As New RandomGenerator
AddHandler gen.ValueFive, AddressOf five.OnFiveEvent
gen.Generate()
End Sub
End Class
End Namespace
```
我们有四个类。 `FiveEventArgs`随事件对象一起传送一些数据。 `Five`类封装了事件对象。 `RandomGenerator`类负责生成随机数。 它是事件发送者。 最后是`Example`类,它是主要的应用对象,具有`Main()`方法。
```vb
Public Class FiveEventArgs
Inherits EventArgs
Public Count As Integer
Public Time As Date
...
```
`FiveEventArgs`在事件对象内部传送数据。 它继承自`EventArgs`基类。 `Count`和`Time`成员是将被初始化并随事件携带的数据。
```vb
If Random = 5 Then
Count += 1
args = New FiveEventArgs(Count, Now)
RaiseEvent ValueFive(Me, args)
End If
```
如果生成的随机数等于 5,我们用当前的`Count`和`Date`值实例化`FiveEventArgs`类。 `Count`变量对生成此事件的次数进行计数。 `Time`值保留事件生成的时间。 使用带有发送者对象和事件参数的`RaiseEvent`关键字发送事件。
```vb
AddHandler gen.ValueFive, AddressOf five.OnFiveEvent
```
我们将`ValueFive`事件插入其处理器。
```vb
$ ./event2.exe
3
6
5
Five event 1 occured at 9/15/2010 5:06:13 PM
3
5
Five event 2 occured at 9/15/2010 5:06:13 PM
6
3
2
5
Five event 3 occured at 9/15/2010 5:06:13 PM
2
5
Five event 4 occured at 9/15/2010 5:06:13 PM
```
这是我在计算机上得到的输出。
在 Visual Basic 教程的这一部分中,我们继续讨论 Visual Basic 中的面向对象编程。
- ZetCode 数据库教程
- MySQL 教程
- MySQL 简介
- MySQL 安装
- MySQL 的第一步
- MySQL 快速教程
- MySQL 存储引擎
- MySQL 数据类型
- 在 MySQL 中创建,更改和删除表
- MySQL 表达式
- 在 MySQL 中插入,更新和删除数据
- MySQL 中的SELECT语句
- MySQL 子查询
- MySQL 约束
- 在 MySQL 中导出和导入数据
- 在 MySQL 中连接表
- MySQL 函数
- MySQL 中的视图
- MySQL 中的事务
- MySQL 存储过程
- MySQL Python 教程
- MySQL Perl 教程
- MySQL & Perl DBI
- 使用 Perl 连接到 MySQL 数据库
- MySQL 中的 Perl 错误处理
- 使用 Perl 进行 MySQL 查询
- 在 MySQL 中使用 Perl 绑定参数&列
- 在 MySQL 中使用 Perl 处理图像
- 使用 Perl 获取 MySQL 元数据
- Perl 的 MySQL 事务
- MySQL C API 编程教程
- MySQL Visual Basic 教程
- MySQL PHP 教程
- MySQL Java 教程
- MySQL Ruby 教程
- MySQL C# 教程
- SQLite 教程
- SQLite 简介
- sqlite3 命令行工具
- 在 SQLite 中创建,删除和更改表
- SQLite 表达式
- SQLite 插入,更新,删除数据
- SQLite SELECT语句
- SQLite 约束
- SQLite 连接表
- SQLite 函数
- SQLite 视图,触发器,事务
- SQLite C 教程
- SQLite Python 教程
- SQLite Perl 教程
- Perl DBI
- 使用 Perl 连接到 SQLite 数据库
- SQLite Perl 错误处理
- 使用 Perl 的 SQLite 查询
- 使用 Perl 绑定 SQLite 参数&列
- 使用 Perl 在 SQLite 中处理图像
- 使用 Perl 获取 SQLite 元数据
- 使用 Perl 进行 SQLite 事务
- SQLite Ruby 教程
- 连接到 SQLite 数据库
- 在 SQLite 中使用 Ruby 进行 SQL 查询
- 绑定参数
- 处理图像
- 使用 Ruby 获取 SQLite 元数据
- Ruby 的 SQLite 事务
- SQLite C# 教程
- SQLite C# 简介
- 使用SqliteDataReader检索数据
- ADO.NET 数据集
- 使用 C# 在 SQLite 中处理图像
- 使用 C# 获取 SQLite 元数据
- 使用 C# 的 SQLite 事务
- SQLite Visual Basic 教程
- SQLite Visual Basic 简介
- 使用SqliteDataReader检索数据
- ADO.NET 的数据集
- 使用 Visual Basic 在 SQLite 中处理图像
- 使用 Visual Basic 获取 SQLite 元数据
- 使用 Visual Basic 的 SQLite 事务
- PostgreSQL C 教程
- PostgreSQL Ruby 教程
- PostgreSQL PHP 教程
- PostgreSQL PHP 编程简介
- 在 PostgreSQL 中使用 PHP 检索数据
- 在 PostgreSQL 中使用 PHP 处理图像
- 用 PHP 获取 PostgreSQL 元数据
- 在 PostgreSQL 中使用 PHP 进行事务
- PostgreSQL Java 教程
- Apache Derby 教程
- Derby 简介
- Derby 的安装&配置
- Derby 工具
- ij 工具
- Derby 中的 SQL 查询
- 在 Derby 中使用 JDBC 进行编程
- Derby 安全
- 使用 Derby & Apache Tomcat
- NetBeans 和 Derby
- SQLAlchemy 教程
- SQLAlchemy 简介
- 原始 SQL
- 模式定义语言
- SQL 表达式语言
- SQLAlchemy 中的对象关系映射器
- MongoDB PHP 教程
- MongoDB JavaScript 教程
- MongoDB Ruby 教程
- Spring JdbcTemplate 教程
- JDBI 教程
- MyBatis 教程
- Hibernate Derby 教程
- ZetCode .NET 教程
- Visual Basic 教程
- Visual Basic
- Visual Basic 语法结构
- 基本概念
- Visual Basic 数据类型
- Visual Basic 中的字符串
- 运算符
- 控制流
- Visual Basic 数组
- Visual Basic 中的过程&函数
- 在 Visual Basic 中组织代码
- 面向对象编程
- Visual Basic 中的面向对象编程 II
- Visual Basic 中的集合
- 输入和输出
- C# 教程
- C# 语言
- C# 语法结构
- C# 基础
- C# 数据类型
- C# 中的字符串
- C# 运算符
- C# 中的流控制
- C# 数组
- C# 面向对象编程
- C# 中的方法
- C# 面向对象编程 II
- C# 属性
- C# 结构
- C# 委托
- 命名空间
- C# 集合
- C# 输入和输出
- C# 目录教程
- C# 字典教程
- 在 C# 中读取文本文件
- C# 中的日期和时间
- 在 C# 中读取网页
- C# HttpClient教程
- ASP.NET Core 教程
- ZetCode 图形教程
- Java 2D 游戏教程
- Java 游戏基础
- 动画
- 移动精灵
- 碰撞检测
- Java 益智游戏
- Java Snake
- Breakout 游戏
- Java 俄罗斯方块
- Java 吃豆人
- Java 太空侵略者
- Java 扫雷
- Java 推箱子
- Java 2D 教程
- 介绍
- 基本绘图
- 形状和填充
- 透明度
- 合成
- 剪裁
- 变换
- 特效
- 图像
- 文字和字体
- 命中测试,移动物体
- 俄罗斯方块
- Cario 图形教程
- Cario 图形库
- Cario 定义
- Cairo 后端
- Cairo 基本图形
- 形状和填充
- 渐变
- 透明度
- 合成
- 剪裁和遮罩
- 变换
- Cairo 文字
- Cairo 中的图像
- 根窗口
- PyCairo 教程
- PyCairo 简介
- PyCairo 后端
- PyCairo 中的基本绘图
- PyCairo 形状和填充
- PyCairo 渐变
- PyCairo 剪裁&遮罩
- PyCairo 的透明度
- PyCairo 中的变换
- PyCairo 中的文字
- PyCairo 中的图像
- 根窗口
- HTML5 画布教程
- 介绍
- HTML5 画布中的直线
- HTML5 画布形状
- HTML5 画布填充
- HTML5 画布中的透明度
- HTML5 画布合成
- HTML5 canvas 中的变换
- HTML5 画布中的文字
- HTML5 画布中的动画
- HTML5 画布中的 Snake
- ZetCode GUI 教程
- Windows API 教程
- Windows API 简介
- Windows API main函数
- Windows API 中的系统函数
- Windows API 中的字符串
- Windows API 中的日期和时间
- Windows API 中的一个窗口
- UI 的第一步
- Windows API 菜单
- Windows API 对话框
- Windows API 控件 I
- Windows API 控件 II
- Windows API 控件 III
- Windows API 中的高级控件
- Windows API 中的自定义控件
- Windows API 中的 GDI
- PyQt4 教程
- PyQt4 简介
- PyQt4 中的第一个程序
- PyQt4 中的菜单和工具栏
- PyQt4 中的布局管理
- PyQt4 中的事件和信号
- PyQt4 中的对话框
- PyQt4 小部件
- PyQt4 小部件 II
- PyQt4 中的拖放
- PyQt4 中的绘图
- PyQt4 中的自定义小部件
- PyQt4 中的俄罗斯方块游戏
- PyQt5 教程
- PyQt5 简介
- PyQt5 日期和时间
- PyQt5 中的第一个程序
- PyQt5 中的菜单和工具栏
- PyQt5 中的布局管理
- PyQt5 中的事件和信号
- PyQt5 中的对话框
- PyQt5 小部件
- PyQt5 小部件 II
- PyQt5 拖放
- PyQt5 中的绘图
- PyQt5 中的自定义小部件
- PyQt5 中的俄罗斯方块
- Qt4 教程
- Qt4 工具包简介
- Qt4 工具类
- Qt4 中的字符串
- Qt4 中的日期和时间
- 在 Qt4 中使用文件和目录
- Qt4 中的第一个程序
- Qt4 中的菜单和工具栏
- Qt4 中的布局管理
- Qt4 中的事件和信号
- Qt4 小部件
- Qt4 小部件 II
- Qt4 中的绘图
- Qt4 中的自定义小部件
- Qt4 中的打砖块游戏
- Qt5 教程
- Qt5 工具包简介
- Qt5 中的字符串
- Qt5 中的日期和时间
- Qt5 中的容器
- 在 Qt5 中处理文件和目录
- Qt5 中的第一个程序
- Qt5 中的菜单和工具栏
- Qt5 中的布局管理
- Qt5 中的事件和信号
- Qt5 小部件
- Qt5 小部件 II
- Qt5 中的绘图
- Qt5 中的自定义小部件
- Qt5 中的贪食蛇
- Qt5 中的打砖块游戏
- PySide 教程
- PySide 工具包简介
- PySide 中的第一个程序
- PySide 中的菜单和工具栏
- PySide 中的布局管理
- PySide 中的事件和信号
- PySide 中的对话框
- PySide 小部件
- PySide 小部件 II
- 在 PySide 中拖放
- 在 PySide 中绘图
- PySide 中的自定义小部件
- PySide 中的俄罗斯方块游戏
- Tkinter 教程
- Tkinter 简介
- Tkinter 中的布局管理
- Tkinter 标准小部件属性
- Tkinter 小部件
- Tkinter 中的菜单和工具栏
- Tkinter 中的对话框
- Tkinter 中的绘图
- Tkinter 中的贪食蛇
- Tcl/Tk 教程
- Tcl/Tk 简介
- Tcl/Tk 中的布局管理
- Tcl/Tk 小部件
- Tcl/Tk 中的菜单和工具栏
- Tcl/Tk 中的对话框
- Tcl/Tk 绘图
- 贪食蛇
- Qt 快速教程
- Java Swing 教程
- Java Swing 简介
- Java Swing 首个程序
- Java Swing 中的菜单和工具栏
- Swing 布局管理
- GroupLayout管理器
- Java Swing 事件
- 基本的 Swing 组件
- 基本的 Swing 组件 II
- Java Swing 对话框
- Java Swing 模型架构
- Swing 中的拖放
- Swing 中的绘图
- Java Swing 中的可调整大小的组件
- Java Swing 中的益智游戏
- 俄罗斯方块
- JavaFX 教程
- JavaFX 简介
- JavaFX 首个程序
- JavaFX 布局窗格
- 基本的 JavaFX 控件
- 基本 JavaFX 控件 II
- JavaFX 事件
- JavaFX 效果
- JavaFX 动画
- JavaFX 画布
- JavaFX 图表
- Java SWT 教程
- Java SWT 简介
- Java SWT 中的布局管理
- Java SWT 中的菜单和工具栏
- Java SWT 中的小部件
- Table小部件
- Java SWT 中的对话框
- Java SWT 绘图
- Java SWT 中的贪食蛇
- wxWidgets 教程
- wxWidgets 简介
- wxWidgets 助手类
- wxWidgets 中的第一个程序
- wxWidgets 中的菜单和工具栏
- wxWidgets 中的布局管理
- wxWidgets 中的事件
- wxWidgets 中的对话框
- wxWidgets 小部件
- wxWidgets 小部件 II
- wxWidgets 中的拖放
- wxWidgets 中的设备上下文
- wxWidgets 中的自定义小部件
- wxWidgets 中的俄罗斯方块游戏
- wxPython 教程
- wxPython 简介
- 第一步
- 菜单和工具栏
- wxPython 中的布局管理
- wxPython 中的事件
- wxPython 对话框
- 小部件
- wxPython 中的高级小部件
- wxPython 中的拖放
- wxPython 图形
- 创建自定义小部件
- wxPython 中的应用框架
- wxPython 中的俄罗斯方块游戏
- C# Winforms Mono 教程
- Mono Winforms 简介
- Mono Winforms 中的第一步
- Mono Winforms 中的布局管理
- Mono Winforms 中的菜单和工具栏
- Mono Winforms 中的基本控件
- Mono Winforms 中的高级控件
- 对话框
- Mono Winforms 中的拖放
- Mono Winforms 中的绘图
- Mono Winforms 中的贪食蛇
- Java Gnome 教程
- Java Gnome 简介
- Java Gnome 的第一步
- Java Gnome 中的布局管理
- Java Gnome 中的布局管理 II
- Java Gnome 中的菜单
- Java Gnome 中的工具栏
- Java Gnome 中的事件
- Java Gnome 中的小部件
- Java Gnome 中的小部件 II
- Java Gnome 中的高级小部件
- Java Gnome 中的对话框
- Java Gnome 中的 Pango
- 在 Java Gnome 中用 Cairo 绘图
- Cario 绘图 II
- Java Gnome 中的贪食蛇
- QtJambi 教程
- QtJambi 简介
- QtJambi 中的布局管理
- QtJambi 中的小部件
- QtJambi 中的菜单和工具栏
- QtJambi 对话框
- QtJambi 中的绘图
- QtJambi 中的自定义小部件
- 贪食蛇
- GTK+ 教程
- GTK+ 简介
- GTK+ 中的第一个程序
- GTK+ 中的菜单和工具栏
- GTK+ 布局管理
- GTK+ 事件和信号
- GTK+ 对话框
- GTK+ 小部件
- GTK+ 小部件 II
- GtkTreeView小部件
- GtkTextView小部件
- 自定义 GTK+ 小部件
- Ruby GTK 教程
- Ruby GTK 简介
- Ruby GTK 中的布局管理
- Ruby GTK 中的小部件
- Ruby GTK 中的菜单和工具栏
- Ruby GTK 中的对话框
- Ruby GTK Cario 绘图
- Ruby GTK 中的自定义小部件
- Ruby GTK 中的贪食蛇
- GTK# 教程
- GTK# 简介
- GTK 的第一步
- GTK# 中的布局管理
- GTK 中的菜单
- GTK# 中的工具栏
- GTK# 中的事件
- GTK# 中的小部件
- GTK 中的小部件 II
- GTK# 中的高级小部件
- GTK# 中的对话框
- Pango
- GTK# 中的 Cario 绘图
- GTK# 中的 Cario 绘图 II
- GTK# 中的自定义小部件
- Visual Basic GTK# 教程
- Visual Basic GTK# 简介
- 布局管理
- 小部件
- 菜单和工具栏
- 对话框
- Cario 绘图
- 自定义小部件
- 贪食蛇
- PyGTK 教程
- PyGTK 简介
- PyGTK 的第一步
- PyGTK 中的布局管理
- PyGTK 中的菜单
- PyGTK 中的工具栏
- PyGTK 中的事件和信号
- PyGTK 中的小部件
- PyGTK 中的小部件 II
- PyGTK 中的高级小部件
- PyGTK 中的对话框
- Pango
- Pango II
- PyGTK 中的 Cario 绘图
- Cario 绘图 II
- PyGTK 中的贪食蛇游戏
- PyGTK 中的自定义小部件
- PHP GTK 教程
- PHP GTK 简介
- PHP GTK 中的布局管理
- PHP GTK 中的小部件
- PHP GTK 中的菜单和工具栏
- 对话框
- Cario 绘图
- 自定义小部件
- 贪食蛇
- C# Qyoto 教程
- Qyoto 介绍
- 布局管理
- Qyoto 中的小部件
- Qyoto 中的菜单和工具栏
- Qyoto 对话框
- Qyoto 中的绘图
- Qyoto 中的绘图 II
- Qyoto 中的自定义小部件
- 贪食蛇
- Ruby Qt 教程
- Ruby Qt 简介
- Ruby Qt 中的布局管理
- Ruby Qt 中的小部件
- 菜单和工具栏
- Ruby Qt 中的对话框
- 用 Ruby Qt 绘图
- Ruby Qt 中的自定义小部件
- Ruby Qt 中的贪食蛇
- Visual Basic Qyoto 教程
- Qyoto 介绍
- 布局管理
- Qyoto 中的小部件
- Qyoto 中的菜单和工具栏
- Qyoto 对话框
- Qyoto 中的绘图
- Qyoto 中的自定义小部件
- 贪食蛇
- Mono IronPython Winforms 教程
- 介绍
- IronPython Mono Winforms 中的第一步
- 布局管理
- 菜单和工具栏
- Mono Winforms 中的基本控件
- Mono Winforms 中的基本控件 II
- Mono Winforms 中的高级控件
- 对话框
- Mono Winforms 中的拖放
- 绘图
- IronPython Mono Winforms 中的绘图 II
- IronPython Mono Winforms 中的贪食蛇
- IronPython Mono Winforms 中的俄罗斯方块游戏
- FreeBASIC GTK 教程
- Jython Swing 教程
- Jython Swing 简介
- Jython Swing 中的布局管理
- Jython Swing 中的组件
- Jython Swing 中的菜单和工具栏
- Jython Swing 中的对话框
- Jython Swing 中的绘图
- Jython Swing 中的半字节
- JRuby Swing 教程
- JRuby Swing 简介
- JRuby Swing 中的布局管理
- JRuby Swing 中的组件
- 菜单和工具栏
- JRuby Swing 中的对话框
- 在 JRuby Swing 中绘图
- JRuby Swing 中的贪食蛇
- Visual Basic Winforms 教程
- Visual Basic Winforms 简介
- 布局管理
- 基本控制
- 进阶控件
- 菜单和工具栏
- 对话框
- 绘图
- 拖放
- 贪食蛇
- JavaScript GTK 教程
- JavaScript GTK 简介
- 布局管理
- JavaScript GTK 中的小部件
- JavaScript GTK 中的菜单和工具栏
- JavaScript GTK 中的对话框
- JavaScript GTK 中的 Cario 绘图
- ZetCode Java 教程
- Java 教程
- Java 语言
- Java 语法结构
- Java 基础
- Java 数据类型
- Java 数据类型 II
- Java 字符串
- Java 数组
- Java 表达式
- Java 控制流程
- Java 面向对象的编程
- Java 方法
- Java 面向对象编程 II
- Java 包
- Java 中的异常
- Java 集合
- Java 流
- Java Future 教程
- Java Comparable和Comparator
- Java DOM 教程
- Java MVC 教程
- Java SAX 教程
- Java JAXB 教程
- Java JSON 处理教程
- Java H2 教程
- MongoDB Java 教程
- Java 正则表达式教程
- Java PDFBox 教程
- Java 文件教程
- Java Files.list教程
- Java Files.walk教程
- Java DirectoryStream教程
- Java 外部与内部迭代器
- Java 文件大小
- 用 Java 创建目录
- 用 Java 创建文件
- Java Log4j 教程
- Gson 教程
- Java RequestDispatcher
- Java HTTP GET/POST 请求
- Java InputStream教程
- Java FileOutputStream教程
- Java FileInputStream教程
- Java ZipInputStream教程
- Java FileWriter教程
- EJB 简介
- Java forEach教程
- Jetty 教程
- Tomcat Derby 教程
- Stripes 介绍
- 使用 Stripes 的 Java webapp,MyBatis,& Derby
- EclipseLink 简介
- Java 中的数据源
- JSTL 中的 SQL 查询标记
- Java 验证过滤器
- Hibernate 验证器
- 用 Java 显示图像
- Play 框架简介
- Spark Java 简介
- Java ResourceBundle教程
- Jtwig 教程
- Java Servlet 教程
- Java 套接字教程
- FreeMarker 教程
- Android 教程
- Java EE 5 教程
- JSoup 教程
- JFreeChart 教程
- ImageIcon教程
- 用 Java 复制文件
- Java 文件时间教程
- 如何使用 Java 获取当前日期时间
- Java 列出目录内容
- Java 附加到文件
- Java ArrayList教程
- 用 Java 读写 ICO 图像
- Java int到String的转换
- Java HashSet教程
- Java HashMap教程
- Java static关键字
- Java 中的HashMap迭代
- 用 Java 过滤列表
- 在 Java 中读取网页
- Java 控制台应用
- Java 集合的便利工厂方法
- Google Guava 简介
- OpenCSV 教程
- 用 Java8 的StringJoiner连接字符串
- Java 中元素迭代的历史
- Java 谓词
- Java StringBuilder
- Java 分割字串教学
- Java NumberFormat
- Java TemporalAdjusters教程
- Apache FileUtils教程
- Java Stream 过滤器
- Java 流归约
- Java 流映射
- Java InputStreamReader教程
- 在 Java 中读取文本文件
- Java Unix 时间
- Java LocalTime
- Java 斐波那契
- Java ProcessBuilder教程
- Java 11 的新功能
- ZetCode JavaScript 教程
- Ramda 教程
- Lodash 教程
- Collect.js 教程
- Node.js 简介
- Node HTTP 教程
- Node-config 教程
- Dotenv 教程
- Joi 教程
- Liquid.js 教程
- faker.js 教程
- Handsontable 教程
- PouchDB 教程
- Cheerio 教程
- Axios 教程
- Jest 教程
- JavaScript 正则表达式
- 用 JavaScript 创建对象
- Big.js 教程
- Moment.js 教程
- Day.js 教程
- JavaScript Mustache 教程
- Knex.js 教程
- MongoDB JavaScript 教程
- Sequelize 教程
- Bookshelf.js 教程
- Node Postgres 教程
- Node Sass 教程
- Document.querySelector教程
- Document.all教程
- JSON 服务器教程
- JavaScript 贪食蛇教程
- JavaScript 构建器模式教程
- JavaScript 数组
- XMLHttpRequest教程
- 从 JavaScript 中的 URL 读取 JSON
- 在 JavaScript 中循环遍历 JSON 数组
- jQuery 教程
- Google 图表教程
- ZetCode Kotlin 教程
- Kotlin Hello World 教程
- Kotlin 变量
- Kotlin 的运算符
- Kotlin when表达式
- Kotlin 数组
- Kotlin 范围
- Kotlin Snake
- Kotlin Swing 教程
- Kotlin 字符串
- Kotlin 列表
- Kotlin 映射
- Kotlin 集合
- Kotlin 控制流程
- Kotlin 写入文件
- Kotlin 读取文件教程
- Kotlin 正则表达式
- ZetCode 其它教程
- TCL 教程
- Tcl
- Tcl 语法结构
- Tcl 中的基本命令
- Tcl 中的表达式
- Tcl 中的控制流
- Tcl 中的字符串
- Tcl 列表
- Tcl 中的数组
- Tcl 中的过程
- 输入&输出
- AWK 教程
- Vaadin 教程
- Vaadin 框架介绍
- Vaadin Grid教程
- Vaadin TextArea教程
- Vaadin ComboBox教程
- Vaadin Slider教程
- Vaadin CheckBox教程
- Vaadin Button教程
- Vaadin DateField教程
- Vaadin Link教程
- ZetCode PHP 教程
- PHP 教程
- PHP
- PHP 语法结构
- PHP 基础
- PHP 数据类型
- PHP 字符串
- PHP 运算符
- PHP 中的控制流
- PHP 数组
- PHP 数组函数
- PHP 中的函数
- PHP 正则表达式
- PHP 中的面向对象编程
- PHP 中的面向对象编程 II
- PHP Carbon 教程
- PHP Monolog 教程
- PHP 配置教程
- PHP Faker 教程
- Twig 教程
- Valitron 教程
- Doctrine DBAL QueryBuilder 教程
- PHP Respect 验证教程
- PHP Rakit 验证教程
- PHP PDO 教程
- CakePHP 数据库教程
- PHP SQLite3 教程
- PHP 文件系统函数
- ZetCode Python 教程
- Python 教程
- Python 语言
- 交互式 Python
- Python 语法结构
- Python 数据类型
- Python 字符串
- Python 列表
- Python 字典
- Python 运算符
- Python 关键字
- Python 函数
- Python 中的文件
- Python 中的面向对象编程
- Python 模块
- Python 中的包
- Python 异常
- Python 迭代器和生成器
- Python 内省
- Python Faker 教程
- Python f 字符串教程
- Python bcrypt 教程
- Python 套接字教程
- Python smtplib教程
- OpenPyXL 教程
- Python pathlib教程
- Python YAML 教程
- Python 哈希教程
- Python ConfigParser教程
- Python 日志教程
- Python argparse 教程
- Python SQLite 教程
- Python Cerberus 教程
- Python PostgreSQL 教程
- PyMongo 教程
- PyMySQL 教程
- Peewee 教程
- pyDAL 教程
- pytest 教程
- Bottle 教程
- Python Jinja 教程
- PrettyTable 教程
- BeautifulSoup 教程
- pyquery 教程
- Python for循环
- Python 反转
- Python Lambda 函数
- Python 集合
- Python 映射
- Python CSV 教程-读写 CSV
- Python 正则表达式
- Python SimpleJson 教程
- SymPy 教程
- Pandas 教程
- Matplotlib 教程
- Pillow 教程
- Python FTP 教程
- Python Requests 教程
- Python Arrow 教程
- Python 列表推导式
- Python 魔术方法
- PyQt 中的QPropertyAnimation
- PyQt 中的QNetworkAccessManager
- ZetCode Ruby 教程
- Ruby 教程
- Ruby
- Ruby 语法结构
- Ruby 基础
- Ruby 变量
- Ruby 中的对象
- Ruby 数据类型
- Ruby 字符串
- Ruby 表达式
- Ruby 控制流
- Ruby 数组
- Ruby 哈希
- Ruby 中的面向对象编程
- Ruby 中的面向对象编程 II
- Ruby 正则表达式
- Ruby 输入&输出
- Ruby HTTPClient教程
- Ruby Faraday 教程
- Ruby Net::HTTP教程
- ZetCode Servlet 教程
- 从 Java Servlet 提供纯文本
- Java Servlet JSON 教程
- Java Servlet HTTP 标头
- Java Servlet 复选框教程
- Java servlet 发送图像教程
- Java Servlet JQuery 列表教程
- Servlet FreeMarker JdbcTemplate 教程-CRUD 操作
- jQuery 自动补全教程
- Java servlet PDF 教程
- servlet 从 WAR 内读取 CSV 文件
- Java HttpServletMapping
- EasyUI datagrid
- Java Servlet RESTFul 客户端
- Java Servlet Log4j 教程
- Java Servlet 图表教程
- Java ServletConfig教程
- Java Servlet 读取网页
- 嵌入式 Tomcat
- Java Servlet 分页
- Java Servlet Weld 教程
- Java Servlet 上传文件
- Java Servlet 提供 XML
- Java Servlet 教程
- JSTL forEach标签
- 使用 jsGrid 组件
- ZetCode Spring 教程
- Spring @Bean注解教程
- Spring @Autowired教程
- Spring @GetMapping教程
- Spring @PostMapping教程
- Spring @DeleteMapping教程
- Spring @RequestMapping教程
- Spring @PathVariable教程
- Spring @RequestBody教程
- Spring @RequestHeader教程
- Spring Cookies 教程
- Spring 资源教程
- Spring 重定向教程
- Spring 转发教程
- Spring ModelAndView教程
- Spring MessageSource教程
- Spring AnnotationConfigApplicationContext
- Spring BeanFactoryPostProcessor教程
- Spring BeanFactory教程
- Spring context:property-placeholder教程
- Spring @PropertySource注解教程
- Spring @ComponentScan教程
- Spring @Configuration教程
- Spring C 命名空间教程
- Spring P 命名空间教程
- Spring bean 引用教程
- Spring @Qualifier注解教程
- Spring ClassPathResource教程
- Spring 原型作用域 bean
- Spring Inject List XML 教程
- Spring 概要文件 XML 教程
- Spring BeanDefinitionBuilder教程
- Spring 单例作用域 bean
- 独立的 Spring 应用
- 经典 Spring 应用中的JdbcTemplate
- Spring EmbeddedDatabaseBuilder教程
- Spring HikariCP 教程
- Spring Web 应用简介
- Spring BeanPropertyRowMapper教程
- Spring DefaultServlet教程
- Spring WebSocket 教程
- Spring WebJars 教程
- Spring @MatrixVariable教程
- Spring Jetty 教程
- Spring 自定义 404 错误页面教程
- Spring WebApplicationInitializer教程
- Spring BindingResult教程
- Spring FreeMarker 教程
- Spring Thymeleaf 教程
- Spring ResourceHandlerRegistry教程
- SpringRunner 教程
- Spring MockMvc 教程
- ZetCode Spring Boot 教程
- Spring Boot 发送电子邮件教程
- Spring Boot WebFlux 教程
- Spring Boot ViewControllerRegistry教程
- Spring Boot CommandLineRunner教程
- Spring Boot ApplicationReadyEvent 教程
- Spring Boot CORS 教程
- Spring Boot @Order教程
- Spring Boot @Lazy教程
- Spring Boot Flash 属性
- Spring Boot CrudRepository 教程
- Spring Boot JpaRepository 教程
- Spring Boot findById 教程
- Spring Boot Data JPA @NamedQuery教程
- Spring Boot Data JPA @Query教程
- Spring Boot Querydsl 教程
- Spring Boot Data JPA 排序教程
- Spring Boot @DataJpaTest教程
- Spring Boot TestEntityManager 教程
- Spring Boot Data JPA 派生的查询
- Spring Boot Data JPA 查询示例
- Spring Boot Jersey 教程
- Spring Boot CSV 教程
- SpringBootServletInitializer教程
- 在 Spring Boot 中加载资源
- Spring Boot H2 REST 教程
- Spring Boot RestTemplate
- Spring Boot REST XML 教程
- Spring Boot Moustache 教程
- Spring Boot Thymeleaf 配置
- Spring Boot 自动控制器
- Spring Boot FreeMarker 教程
- Spring Boot Environment
- Spring Boot Swing 集成教程
- 在 Spring Boot 中提供图像文件
- 在 Spring Boot 中创建 PDF 报告
- Spring Boot 基本注解
- Spring Boot @ResponseBody教程
- Spring Boot @PathVariable教程
- Spring Boot REST Data JPA 教程
- Spring Boot @RequestParam教程
- Spring Boot 列出 bean
- Spring Boot @Bean
- Spring Boot @Qualifier教程
- 在 Spring Boot 中提供静态内容
- Spring Boot Whitelabel 错误
- Spring Boot DataSourceBuilder 教程
- Spring Boot H2 教程
- Spring Boot Web JasperReports 集成
- Spring Boot iText 教程
- Spring Boot cmd JasperReports 集成
- Spring Boot RESTFul 应用
- Spring Boot 第一个 Web 应用
- Spring Boot Groovy CLI
- Spring Boot 上传文件
- Spring Boot @ExceptionHandler
- Spring Boot @ResponseStatus
- Spring Boot ResponseEntity
- Spring Boot @Controller
- Spring Boot @RestController
- Spring Boot @PostConstruct
- Spring Boot @Component
- Spring Boot @ConfigurationProperties教程
- Spring Boot @Repository
- Spring Boot MongoDB 教程
- Spring Boot MongoDB Reactor 教程
- Spring Boot PostgreSQL 教程
- Spring Boot @ModelAttribute
- Spring Boot 提交表单教程
- Spring Boot Model
- Spring Boot MySQL 教程
- Spring Boot GenericApplicationContext
- SpringApplicationBuilder教程
- Spring Boot Undertow 教程
- Spring Boot 登录页面教程
- Spring Boot RouterFunction 教程
- ZetCode Symfony 教程
- Symfony DBAL 教程
- Symfony 表单教程
- Symfony CSRF 教程
- Symfony Vue 教程
- Symfony 简介
- Symfony 请求教程
- Symfony HttpClient教程
- Symfony Flash 消息
- 在 Symfony 中发送邮件
- Symfony 保留表单值
- Symfony @Route注解教程
- Symfony 创建路由
- Symfony 控制台命令教程
- Symfony 上传文件
- Symfony 服务教程
- Symfony 验证教程
- Symfony 翻译教程