Vb.net 在VB 2013中用另一个对象包装对象

Vb.net 在VB 2013中用另一个对象包装对象,vb.net,Vb.net,我正在尝试将一个已创建类的实例与另一个在Visual Basic 2013中共享同一个超类的实例包装在一起。我是VB新手,一直在努力解决这个问题 这是用于Java到VB的转换 我所写的代码示例: ' Abstract product creator Class Public MustInherit Class PizzaMaker ' Abstract Method to create a pizza Public MustOverride Function createPizza(ByRef

我正在尝试将一个已创建类的实例与另一个在Visual Basic 2013中共享同一个超类的实例包装在一起。我是VB新手,一直在努力解决这个问题

这是用于Java到VB的转换

我所写的代码示例:

' Abstract product creator Class
Public MustInherit Class PizzaMaker

' Abstract Method to create a pizza
Public MustOverride Function createPizza(ByRef size As Integer, ByRef crust As String) As Pizza

Public Function orderPizza(ByRef size, ByRef crust) As Pizza
    Dim pizza As Pizza
    pizza = createPizza(size, crust)

    Return pizza
End Function
End Class

' Concrete factory Class
Public Class MargheritaMaker
Inherits PizzaMaker

' Override abstrat method in superclass
Public Overrides Function createPizza(ByRef size As Integer, ByRef crust As String) As Pizza
    Dim pizza As New MargheritaPizza(size, crust)

    Return pizza
End Function

End Class

' Abstract component product Class
Public MustInherit Class Pizza
' Consatant variables used for pizza size
Public Const SMALL As Integer = 1
Public Const MEDIUM As Int16 = 2
Public Const LARGE As Int16 = 3
Public Const EXTRA_LARGE As Int16 = 4

' Crust type of pizza
Private crustType As String

' Size of the pizza
Private size As Int16

' Description of the pizza
Public description As String = "Pizza"

' Abstract method to return the cost of the pizza
Public MustOverride Function getCost() As Double

' Returns size description
Public Function getSizeDescription() As String
    Dim desc As String

    ' Determin pizza size and return String description
    If (size = 1) Then
        desc = "Small"
    ElseIf (size = 2) Then
        desc = "Medium"
    ElseIf (size = 3) Then
        desc = "Large"
    Else
        desc = "Extra Large"
    End If

    Return desc
End Function

Public Function getCrust() As String
    Return crustType
End Function

' Sets the pizza crust type
Public Sub setCrust(ByRef crust)
    crustType = crust
End Sub

' Returns the pizza size
Public Function getSize() As Integer
    Return size
End Function

' Set the size of our Pizza
Public Sub setSize(ByVal i)
    size = i
End Sub

' Returns the String description of the pizza
Public Function getDescription() As String
    Return getSizeDescription() + " " + crustType + " " + description
End Function


End Class

' Concrete component product Class defining a Margherita Pizza
Public Class MargheritaPizza
Inherits Pizza
'Dim cost
' Constructor set's the Pizza size, crust type & description
Sub New(ByRef size As Integer, ByRef crust As String)
    setSize(size)
    setCrust(crust)
    description = "Margherita Pizza"
End Sub

' Returns the Pizza base cost based on it's size
Public Overrides Function getCost() As Double
    Dim cost As Double
    If (getSize() = Pizza.SMALL) Then
        'Console.Write("in if" & vbNewLine)
        cost = 9.5
    ElseIf (getSize() = Pizza.MEDIUM) Then
        cost = 10.5
    ElseIf (getSize() = Pizza.LARGE) Then
        cost = 11.5
    ElseIf (getSize() = Pizza.EXTRA_LARGE) Then
        cost = 12.5
    End If
    'Console.Write("in if" * vbNewLine)
    Return cost
End Function

End Class

' Abstract component product decorator Class
Public MustInherit Class PizzaDecorator
Inherits Pizza

' Abstract method that returns decorator description
Public MustOverride Overloads Function getDescription()

End Class

' Concrete component product decorator Class (used as Object wrapper)
Public Class Cheese
Inherits PizzaDecorator

Dim pizza ' As Pizza

' Check that the construtor paramaters are correct!!! Also check scope of variables!!!
Sub New(ByVal pizz)
    pizza = pizz
    'pizza.setSize(pizz.getSize())
    'pizza.setCrust(pizz.getCrust())
End Sub

' Returns cost of product by delegating call to wrapped objects
Public Overrides Function getCost() As Double
    Dim cost ' As Double = pizza.getCost()

    If (pizza.getSize() = pizza.SMALL) Then
        Console.Write(" In cheese pizza = SMALL" & vbNewLine)
        cost += 0.1
    ElseIf (pizza.getSize() = pizza.MEDIUM) Then
        cost += 0.2
    ElseIf (pizza.getSize() = pizza.LARGE) Then
        cost += 0.3
    ElseIf (pizza.getSize() = pizza.EXTRA_LARGE) Then
        cost += 0.4
    End If
    Console.Write(" Pizza size = " + pizza.getSize().ToString & vbNewLine)
    Console.Write(" in end if" & vbNewLine)
    Return cost + pizza.getCost()
End Function

Public Overrides Function getDescription() As Object
    Return pizza.getDescription() + ", Extra Cheese"
End Function

End Class
然后使用以下命令运行测试:

Public Class TestForm

Public margheritaM ' As MargheritaMaker
Public pizza ' As Pizza

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    'Dim m As New MargheritaMaker()
    'Dim pizza
    'Dim margheritaM As New MargheritaMaker()
    margheritaM = New MargheritaMaker()
    pizza = margheritaM.createPizza(1, "Deep Pan")

    MargheritaBox.AppendText(pizza.getDescription() & vbNewLine)
End Sub

Private Sub CheeseButton_Click(sender As Object, e As EventArgs) Handles CheeseButton.Click
    'pizza As New Cheese(pizza)
    pizza = New Cheese(pizza)
    MargheritaBox.AppendText(pizza.getDescription() & vbNewLine)
End Sub

Private Sub CostButton_Click(sender As Object, e As EventArgs) Handles CostButton.Click
    MargheritaBox.AppendText(pizza.getCost() & vbNewLine)
End Sub

Private Sub PepperoniButton_Click(sender As Object, e As EventArgs) Handles PepperoniButton.Click
    pizza = New Pepperoni(pizza)
    MargheritaBox.AppendText(pizza.getDescription() & vbNewLine)
End Sub
End Class
我假设我可以通过单击按钮1创建一个玛格丽塔比萨饼对象集,并通过其工厂方法createPizza为比萨饼指定一个比萨饼对象

然后在cheeseButton上单击我可以包装通过调用pizza=New Cheese(pizza)!!创建的pizza对象!!奶酪类封装了比萨饼的额外配料。我想我可以调用原始披萨对象的成本,wiich将通过包装对象委托成本??就像装饰图案一样

下面是一些输出屏幕截图:

在这里,我点击创建比萨饼,然后计算成本,然后额外的奶酪,最后计算成本,一切似乎都很好

这一次,我还单击了“额外奶酪”并计算了成本,但成本没有正确地通过对象进行委派

在这里,我添加了几个额外的奶酪,还向控制台窗口显示了一些测试输出,控制台窗口在每次包装对象时显示比萨饼的大小,并显示比萨饼大小为0,但最里面的包装除外……我做错了什么

我的第一语言是Java,过去对这项技术没有任何问题,但我对VB 2013很陌生,非常感谢您的帮助

欢迎所有建设性意见

非常感谢


请忽略在测试过程中注释掉的代码

包装

首先,这只是我的观点,术语
包装
在处理
不可继承的
类时使用

例如:

Public Class String2

    Public Sub New(s As String)
        Me.s = s
    End Sub

    Default Public ReadOnly Property Chars(index As Integer) As Char
        Get
            Return Me.s.Chars(index)
        End Get
    End Property

    Public ReadOnly Property Length() As Integer
        Get
            Return s.Length
        End Get
    End Property

    Private ReadOnly s As String

End Class
基类

其次,你把这件事复杂化了。以下代码被剥离以使其更具可读性。请注意,这不是最终解决方案

首先定义
外壳
大小
枚举

Public Enum PizzaCrust As Integer
    [Default] = 0
    DeepPan = 1
End Enum

Public Enum PizzaSize As Integer
    S = 0
    M = 1
    L = 2
    XL = 3
End Enum
您只需要两个基类,
Pizza
Extra

Public MustInherit Class Pizza

    Public Property Crust() As PizzaCrust

    MustOverride ReadOnly Property Description() As String

    Public ReadOnly Property Extras() As List(Of Extra)

    MustOverride ReadOnly Property Name() As String

    Public Property Size() As PizzaSize

    Public Function CalculateCost() As Decimal
        Dim value As Decimal = Me.GetBaseCost(Me.Size)
        For Each extr As Extra In Me.Extras
            value += extr.Cost
        Next
        Return value
    End Function

    Protected MustOverride Function GetBaseCost(size As PizzaSize) As Decimal

End Class

Public MustInherit Class Extra

    Public MustOverride ReadOnly Property Name() As String
    Public MustOverride ReadOnly Property Description() As String
    Public MustOverride ReadOnly Property Cost() As Decimal

End Class
比萨饼

创建一个名为
Pizzas
的名称空间,并将所有Pizzas放在这里

Namespace Pizzas

    Public Class Margarita
        Inherits Pizza

        Public Overrides ReadOnly Property Description() As String

        Public Overrides ReadOnly Property Name() As String

        Protected Overrides Function GetBaseCost(size As PizzaSize) As Decimal
            Select Case size
                Case PizzaSize.S
                    Return 10
                Case PizzaSize.M
                    Return 15
                Case PizzaSize.L
                    Return 20
                Case PizzaSize.XL
                    Return 30
                Case Else
                    Return 0
            End Select
        End Function

    End Class

    Public Class Quattro
        Inherits Pizza

        Public Overrides ReadOnly Property Description() As String
        Public Overrides ReadOnly Property Name() As String
        Protected Overrides Function GetBaseCost(size As PizzaSize) As Decimal

    End Class

End Namespace
附加服务

最后,创建一个名为
Extras
的名称空间,并将所有的Extras放在这里

Namespace Extras

    Public Class Cheese
        Inherits Extra

        Public Overrides ReadOnly Property Cost() As Decimal
        Public Overrides ReadOnly Property Description() As String
        Public Overrides ReadOnly Property Name() As String

    End Class

    Public Class Ham
        Inherits Extra

        Public Overrides ReadOnly Property Cost() As Decimal
        Public Overrides ReadOnly Property Description() As String
        Public Overrides ReadOnly Property Name() As String

    End Class

    Public Class Pineapple
        Inherits Extra

        Public Overrides ReadOnly Property Cost() As Decimal
        Public Overrides ReadOnly Property Description() As String
        Public Overrides ReadOnly Property Name() As String

    End Class

End Namespace
用法

现在,要创建一个新的
玛格丽塔
比萨饼,可以这样做:

Dim pizza As New Pizzas.Margarita()

pizza.Size = PizzaSize.L
pizza.Crust = PizzaCrust.DeepPan
pizza.Extras.Add(New Extras.Ham())
pizza.Extras.Add(New Extras.Cheese())

帮自己一个大忙,打开optionstrict和optionexplicit()。这并不能解决您眼前的问题,但它会让您省去调试此程序和其他程序时的麻烦。您可能希望进行调查,以替换您的
常量。大小常量也有混合类型,一些是Int16,一个是整数(根据编译设置,可以是Int16或Int32)。