Is it possible to restrict instantiation of an object to only one other (parent) object in VB.NET?
VB 2008 .NET 3.5
Suppose we have two classes, Order and OrderItem, that represent some type of online ordering system. OrderItem represents a single line item in an Order. One Order can contain multiple OrderItems, in the form of a List(of OrderItem).
Public Class Order
Public Property MyOrderItems() as List(of OrderItem)
End Property
End Class
It makes sense that an OrderItem should not exist without an Order. In other words, an OrderItem class should not be able to be instantiated on its own, it should be dependent on an Order class to contain it and instantiate it. However, the OrderItem should be public in scope so that it's properties are accessible to other objects. So, the requirements for OrderItem are:
Can only be instantiated by the Order class.
Must be public so that any other object can access it's properties/metho开发者_如何学编程ds through the Order object. e.g. Order.OrderItem(0).ProductID.
OrderItem should be able to be passed to other subs/functions that will operate on it.
How can I achieve these goals? Is there a better approach?
You can make a single constructor of OrderItem
that takes an Order
item.
In this constructor, you can add the OrderItem
to the Order.MyOrderItems
collection.
This will satisfy your requirements.
Public Class OrderItem
Public Sub New(ByRef myOrder As Order)
myOrder.MyOrderItems.Add(Me)
End Sub
End Class
- You can only instantiate
OrderItem
by passing in a validOrder
object to it. - Still public and can be called as required (
Order.OrderItem(0).ProductID
). - OrderItem can be passed to other subs and functions.
The standard way to do this is to expose the OrderItem as an interface and then implement it in a private class inside the Order class. The OrderItem class can only be instantiated inside the Order class but it can be exposed to the outside through the public IOrderItem interface. Like so:
Public Interface IOrderItem
ReadOnly Property ItemCode() As Integer
ReadOnly Property NumberOfItems() As Integer
ReadOnly Property Description() As String
End Interface
Public Class Order
Private m_Items As List(Of IOrderItem)
Public ReadOnly Property Items() As List(Of IOrderItem)
Get
Return m_Items
End Get
End Property
Private Class OrderItem
Implements IOrderItem
Private m_Code As Integer
Private m_NumItems As Integer
Private m_Description As String
Public Sub New(ByVal code As Integer, ByVal numItems As Integer, ByVal desc As String)
m_Code = code
m_NumItems = numItems
m_Description = desc
End Sub
Public ReadOnly Property Description() As String Implements IOrderItem.Description
Get
Return m_Description
End Get
End Property
Public ReadOnly Property ItemCode() As Integer Implements IOrderItem.ItemCode
Get
Return m_Code
End Get
End Property
Public ReadOnly Property NumberOfItems() As Integer Implements IOrderItem.NumberOfItems
Get
Return m_NumItems
End Get
End Property
End Class
End Class
OrderItem
's constructor should be friend
(accesible only to Order
) - I say friend
because using friend
you can limit the visibility of the OrderItem
's constructor to classes in the same assembly. Note: this solution implies that Order and OrderItem are in one library/assembly and you are trying to use them from another assembly - otherwise the friend
protection does not work.
The responsablity for creating OrderItem
objects should belong only to Order
:
Build a method like on the Order
class: Public Function CreateOrderItem(whateverParametersYouNeed) as OrderItem
that internally instantiates a new OrderItem
, adds it to the OrderItem
list and returns reference to the newly created item.
You can then do whatever you want with this OrderItem
- it will always belong to the Order
's list.
精彩评论