public abstract partial class AnimalFormBase<T>:Form where T:Animal {...}
然后,您可以从该表单派生以创建特定于动物的表单:
public partial class AnimalForm:AnimalFormBase<Animal> {...}
public partial class BirdForm:AnimalFormBase<Bird> {...}
public partial class DogForm:AnimalFormBase<Dog> {...}
Public Enum AnimalTypes
Animal = 1
Pig = 2
Human = 3
End Enum
Public Class AnimalBase
Public Overridable ReadOnly Property AnimalType() As AnimalTypes
Get
Return AnimalTypes.Animal
End Get
End Property
Public Sub Move(ByVal X As Integer, ByVal Y As Integer)
' . . . You movement code
End Sub
End Class
现在你的派生类:
Public Class Pig
Inherits AnimalBase
Public Overrides ReadOnly Property AnimalType() As AnimalTypes
Get
Return AnimalTypes.Pig
End Get
End Property
'A property spcific to the pig class:
Public ReadOnly Property PigOnEquality() As String
Get
Return "Some pigs are more equal!"
End Get
End Property
End Class
Public Class Human
Inherits AnimalBase
Public Overrides ReadOnly Property AnimalType() As AnimalTypes
Get
Return AnimalTypes.Human
End Get
End Property
'A property specific to the Human class:
Public ReadOnly Property Shotgun() As String
Get
Return "Boom!"
End Get
End Property
End Class
Public Class AnimalFactory
Public Shared Function NewAnimal(ByVal AnimalType As AnimalTypes) As AnimalBase
Select Case AnimalType
Case AnimalTypes.Animal
Return New AnimalBase
Case AnimalTypes.Pig
Return New Pig
Case AnimalTypes.Human
Return New Human
Case Else
Return New AnimalBase
End Select
End Function
End Class
Public Class AnimalFarm ' My hilarious name for the FORM
'Member variable for the currently selected instance of AnimalBase
Private SelectedAnimal As AnimalBase
Private Sub AnimalFarm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Using the enum to populate the comboBox:
With Me.ComboBox1.Items
.Add(AnimalTypes.Animal)
.Add(AnimalTypes.Pig)
.Add(AnimalTypes.Human)
End With
End Sub
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim AnimalType As AnimalTypes = Me.ComboBox1.SelectedItem
Me.OnNewAnimalSelected(AnimalType)
End Sub
Private Sub OnNewAnimalSelected(ByVal AnimalType As AnimalTypes)
SelectedAnimal = AnimalFactory.NewAnimal(AnimalType)
'The form doesn't case what type of animal is being instantiated, so long
'as the methods required are defined on the base class:
MsgBox(SelectedAnimal.AnimalType.ToString)
'Move the animal a bit, just for kicks:
SelectedAnimal.Move(NewX, NewY)
' . . . But if you NEED the specific TYPE of animal:
Select Case SelectedAnimal.AnimalType
Case AnimalTypes.Human
Dim NewHuman As Human = CType(SelectedAnimal, Human)
MsgBox(NewHuman.Shotgun)
Case AnimalTypes.Pig
Dim Piggy As Pig = CType(SelectedAnimal, Pig)
MsgBox(Piggy.PigOnEquality)
Case Else
MsgBox("This Animal has nothing to say . . .")
End Select
End Sub
Private Sub OnMoveAnimal(ByVal X As Integer, ByVal Y As Integer)
SelectedAnimal.Move(X, Y)
End Sub
End Class
2 回答
您是否要创建并显示与选择表单分开的新表单?如果是这样,您可以使表单类通用,仅限于Animal类型的对象:
然后,您可以从该表单派生以创建特定于动物的表单:
如果你想要相同的形式但不同的控件,我会使上述类派生自UserControl . 然后,当用户更改单选按钮时,您可以删除旧动物类型的控件并将其替换为新动物的控件 . 无论哪种方式,通用祖先AnimalFormBase都可以保存与任何Animal相关的功能 . 它可以在技术上包含控件,但我发现设计器渲染类中的自定义继承可能会变得混乱 . 然后,三个派生形式可以使用基本功能,添加它们自己的,并布置每个将呈现给用户的控件 .
我的例子是在vb.net(我正在学习C#,但不是“那里” - 差异不是很大,以至于这没有意义,尽管......),但要点是失败的普遍性 . 你有一个基类Animal,还有一些派生自动物的类 . 在基类上定义.Move方法 . 然后创建派生类,继承基类的方法和公共接口 . 定义AnimalType属性以区分动物类型 . 对于这个非常简单的例子,我使用了一个Enum . 实际上,这可能是Enum,也可能是数据库PK或其他唯一标识符 . 请注意,在实践中,我可能不会使superType Animal成为与派生类相同枚举的成员 . 在DataBase中,我可能会将派生对象“子”记录与“父”动物记录相关联,例如:
现在你的派生类:
现在,一个AnimalFactory类,它将动物和类的实例从动物类型中分离出来(再一次......类型动物):
这里的诀窍是,AnimalFacorty返回的派生类是动物类型,但实现了所有类型的真实类型,如果需要,可以转换为它们的真实类型 . 现在,你的表格 . 如果您只访问基类上定义的常用方法,那么您的表单无需关心返回哪种类型的动物 . 如果需要访问特定于派生类的方法,则需要执行转换操作(在VB#中与C#中的操作相同(或非常相似)) .
我在这种形式中抛出了一些非常愚蠢的例子 . 还有一些方法可以避免Select Case(我相信你会知道它作为一个Switch语句),但我不知道你在使用你的代码做什么,所以这只是一个疯狂的练习 . . .