gpt4 book ai didi

vb.net - VB.NET类或模块的目的是什么?

转载 作者:行者123 更新时间:2023-12-04 08:59:02 24 4
gpt4 key购买 nike

这里有新手酱...所以,我试图找到答案,但是找不到。

拥有一个类或模块的目的是什么?我阅读的所有内容都试图告诉我它是什么,但不是目的。我为什么要做一个?

我阅读的所有内容似乎都是对阅读本教程的人的假设,好像我了解很多。

最佳答案

模块实际上与仅包含共享成员的类非常相似。实际上,在C#中,没有诸如“模块”之类的构造。如果没有至少一个模块或类,您将无法编写任何应用程序,因此我怀疑您的真正问题不是“为什么使用类和模块”,而是“为什么使用多个类和模块以及何时启动一个新的类和模块” 。由于模块和类本质上是同一件事,所以我仅关注为什么您将拥有多个类。创建新类的主要原因主要有四个:


将数据存储在谨慎的项目中
整理您的代码
在代码中提供接缝
将您的代码分为几层并支持n层


现在,让我们更详细地看看每个:

将数据存储在谨慎的项目中

通常,您需要存储有关单个项目的多个数据,并将该数据作为单个对象在方法之间传递。例如,如果您编写一个与某人一起工作的应用程序,则可能要存储有关该人的多个数据,例如其姓名,年龄和职务。您显然可以将这三个数据存储为三个单独的变量,并将它们作为单独的参数传递给方法,例如:

Public Sub DisplayPerson(name As String, age As Integer, title As String)
Label1.Text = name
Label2.Text = age.ToString()
Label3.Text = title
End Sub


但是,将所有数据作为单个对象传递通常更方便,例如,您可以创建一个 MyPersonClass,如下所示:

Public Class MyPersonClass
Public Name As String
Public Age As Integer
Public Title As String
End Class


然后,您可以在单个参数中传递有关某个人的所有数据,如下所示:

Public Sub DisplayPerson(person As MyPersonClass)
Label1.Text = person.Name
Label2.Text = person.Age.ToString()
Label3.Text = person.Title
End Sub


通过这种方式,将来可以更轻松地修改您的人。例如,如果您需要添加存储人员技能的功能,并且没有将人员数据放入类中,则必须遍历代码中传递人员数据的每个位置并添加其他参数。在大型项目中,很难找到所有要修复的地方,这可能会导致错误。但是,当您开始需要存储多个人的列表时,对班级的需求变得更加明显。例如,如果您需要为10个不同的人存储数据,则需要一个变量列表或数组,例如:

Dim names(9) As String
Dim ages(9) As Integer
Dim titles(9) As String


当然, names(3)age(3)都存储同一个人的数据一点也不明显。那只是您必须知道的,或者您必须在评论中写出来,以免忘记。但是,当您有一个类来存储一个人的所有数据时,这样做会更清洁,更轻松:

Dim persons(9) As Person


现在,很明显 persons(3).Namepersons(3).Age都是同一个人的数据。这样,它就是自我记录。无需注释即可阐明您的逻辑。结果,再次,该代码将不那么容易出错。

通常,类不仅包含特定项目的数据,而且还包含作用于该数据的方法。这是一种方便的机制。例如,您可能要向个人类添加 GetDesciption方法,例如:

Public Class MyPersonClass
Public Name As String
Public Age As Integer
Public Title As String

Public Function GetDescription() As String
Return Title & " " & Name
End Function
End Class


然后,您可以像这样使用它:

For Each person As MyPersonClass In persons
MessageBox.Show("Hello " & person.GetDescription())
Next


我敢肯定,您会同意,与做这样的事情相比,哪一种方法更干净,更容易:

For i As Integer = 0 To 9
MessageBox.Show("Hello " & GetPersonDescription(title(i), names(i)))
Next


现在,假设您要为每个人存储多个昵称。如您所见, persons(3).Nicknames(0)比一些疯狂的二维数组(例如 nicknames(3)(0))要简单得多。如果您需要存储有关每个昵称的多个数据,会发生什么?如您所见,不使用类会很快变得混乱。

整理您的代码

当您编写冗长的程序时,如果您没有适当地组织代码,它可能会很快变得非常混乱,并导致非常混乱的代码。在与意大利面条代码的斗争中,您拥有的最重要的武器是创建更多的类。理想情况下,每个类将只包含逻辑上彼此直接相关的方法。每种新的功能类型都应细分为一个新的命名良好的类。在大型项目中,应该将这些类进一步组织到单独的命名空间中,但是如果您至少不将其拆分为类,那么您确实会陷入困境。例如,假设您将以下方法全部丢入同一模块:


GetPersonDescription
GetProductDescription
FirePerson
SellProduct


我相信您会同意,如果将这些方法分解为单独的类,则遵循代码要容易得多,例如:


Person

GetDescription
Fire

Product

GetDescription
Sell



那只是一个非常非常简单的例子。当您拥有处理许多不同项目和不同类型项目的成千上万种方法和变量时,我相信您可以轻松想象为什么类对于帮助组织和自我记录代码很重要。

在代码中提供接缝

这可能会更高级,但它非常重要,因此我将尝试用简单的术语进行解释。假设您创建了一个跟踪记录器类,该类将日志条目写入跟踪日志文件。例如:

Public Class TraceLogger
Public Sub LogEntry(text As String)
' Append the time-stamp to the text
' Write the text to the file
End Sub
End Class


现在,假设您要使logger类能够写入文件或数据库。此时,很明显,将日志条目写入文件实际上是一种单独的逻辑,应该一直属于其自己的类,因此可以将其分解为一个单独的类,如下所示:

Public Class TextFileLogWriter
Public Sub WriteEntry(text As String)
' Write to file
End Sub
End Class


现在,您可以创建一个公共接口,并在两个不同的类之间共享它。这两个类都将处理写日志条目,但是它们各自将以完全不同的方式执行功能:

Public Interface ILogWriter
Sub WriteEntry(text As String)
End Interface

Public Class TextFileLogWriter
Implements ILogWriter

Public Sub WriteEntry(text As String) Implements ILogWriter.WriteEntry
' Write to file
End Sub
End Class

Public Class DatabaseLogWriter
Implements ILogWriter

Public Sub WriteEntry(text As String) Implements ILogWriter.WriteEntry
' Write to database
End Sub
End Class


现在,您已经将数据访问逻辑分解为自己的类,可以按以下方式重构记录器类:

Public Class TraceLogger
Public Sub New(writer As ILogWriter)
_writer = writer
End Sub

Private _writer As ILogWriter

Public Sub LogEntry(text As String)
' Append the time-stamp to the text
_writer.WriteEntry(text)
End Sub
End Class


现在,您可以在更多情况下重用 TraceLogger类,而无需接触该类。例如,您可以给它一个 ILogWriter对象,该对象将条目写入Windows事件日志,电子表格,甚至甚至是电子邮件中,而无需触及原始的 TraceLogger类。这是可能的,因为您已在逻辑形式的条目格式化和条目写入之间创建了接缝。

格式不关心条目如何记录。它关心的只是如何格式化条目。当需要写入和输入时,它只是要求一个单独的writer对象来完成那部分工作。该作者在内部实际执行的操作和方式无关紧要。同样,作者并不关心条目的格式,它只是希望传递给它的内容是已格式化的有效条目,需要记录。

您可能已经注意到, TraceLogger现在不仅可重用以写入任何类型的日志,而且写入器可重用以将任何类型的日志写入那些类型的日志。例如,您可以重用 DatabaseLogWriter来编写跟踪日志和异常日志。

关于依赖注入的小事

在给我一些重要的东西之前,我对这个问题的回答要更长一些,在这个问题上,我有点幽默...在最后一个示例中,我使用了一种称为依赖注入(DI)的技术。之所以称为依赖注入,是因为writer对象是logger类的依赖,并且该依赖对象通过构造函数注入到logger类中。您可以通过执行以下操作来完成类似的操作而无需依赖注入:

Public Class TraceLogger
Public Sub New(mode As LoggerModeEnum)
If mode = LoggerModeEnum.TextFile Then
_writer = New TextFileLogWriter()
Else
_writer = New DatabaseLogWriter()
End If
End Sub

Private _writer As ILogWriter

Public Sub LogEntry(text As String)
' Append the time-stamp to the text
_writer.WriteEntry(text)
End Sub
End Class


但是,如您所见,如果您这样做的话,现在您每次创建新类型的writer时都需要修改该logger类。然后,仅创建一个记录器,就必须引用每种不同类型的编写器。当您以这种方式编写代码时,很快,任何时候只要包含一个类,您就突然必须引用整个世界才能完成一个简单的任务。

依赖项注入方法的另一种替代方法是使用继承来创建多个 TraceLogger类,每种类型的writer都可以创建一个:

Public MustInherit Class TraceLogger
Public Sub New()
_writer = NewLogWriter()
End Sub

Private _writer As ILogWriter

Protected MustOverride Sub NewLogWriter()

Public Sub LogEntry(text As String)
' Append the time-stamp to the text
_writer.WriteEntry(text)
End Sub
End Class

Public Class TextFileTraceLogger
Inherits TraceLogger

Protected Overrides Sub NewLogWriter()
_Return New TextFileLogWriter()
End Sub
End Class

Public Class DatabaseTraceLogger
Inherits TraceLogger

Protected Overrides Sub NewLogWriter()
_Return New DatabaseLogWriter()
End Sub
End Class


像这样,通过继承进行操作比使用模式枚举方法要好,因为不必为了引用到文本文件而引用所有数据库逻辑,但是在我看来,依赖注入更加简洁,更加灵活。

返回逻辑接缝摘要

因此,总而言之,逻辑中的接缝对于代码的可重用性,灵活性和可互换性很重要。在小型项目中,这些事情并不是最重要的,但是随着项目的发展,清晰的接缝可能变得至关重要。

创建接缝的另一个大好处是,它使代码更加稳定和可测试。一旦知道了 TraceLogger的工作原理,便可以将其扩展以供将来使用,例如将日志写入电子表格,而无需接触实际的 TraceLogger类,这是一个很大的优势。如果您不必触摸它,那么您就不必冒险引入新的错误并有可能破坏已经使用它的其余代码。而且,隔离测试每一段代码变得容易得多。例如,如果您想测试 TraceLogger类,则可以使用一个伪造的writer对象来进行测试,该对象只是记录到内存,控制台或其他内容中。

将您的代码分为几层并支持N层

将代码正确地组织到单独的类中后,每个类仅负责一种类型的任务,然后就可以开始将您的类分组在一起。层只是代码的高级组织。从语言上讲,没有什么东西可以具体地构成一层。由于语言中没有直接说明每一层开始和结束的位置的语言,因此人们经常将每一层的所有类放入单独的命名空间中。因此,例如,您可能具有如下所示的名称空间(其中每个名称空间是一个单独的层):


MyProduct.Presentation
MyProduct.Business
MyProduct.DataAccess


通常,您始终希望代码中至少包含两层:表示层或用户界面层以及业务逻辑层。如果您的应用程序执行任何数据访问,则通常也将其放置在其自己的层中。每层应尽可能独立且可互换。因此,例如,如果上面示例中的 TraceLogger类在业务层中,则该类应可在任何类型的UI中重用。

通过提供进一步的组织,自文档,可重用性和稳定性,这些层扩展了所有先前的主题。但是,各层的另一个主要优点是将应用程序分成多个层变得容易得多。例如,如果您需要将业务和数据访问逻辑移动到Web服务中,那么,如果您已经将代码干净地编写到定义的层中,那么这样做非常简单。但是,如果所有逻辑都是混杂的和相互依赖的,那么尝试将数据访问和业务逻辑分解为一个单独的项目将是一场噩梦。

我必须说的话

简而言之,您无需创建多个类或模块。始终可以在单个类或模块中编写整个应用程序。毕竟,在发明面向对象的语言之前就已经开发了整个操作系统和软件套件。但是,有一个原因使面向对象编程(OOP)语言如此流行。对于许多项目而言,面向对象是非常有益的。

关于vb.net - VB.NET类或模块的目的是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14085784/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com