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)
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/methods 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?
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
You can make a single constructor of
OrderItem that takes an
In this constructor, you can add the
OrderItem to the
This will satisfy your requirements.
Public Class OrderItem Public Sub New(ByRef myOrder As Order) myOrder.MyOrderItems.Add(Me) End Sub End Class
OrderItemby passing in a valid
Orderobject to it.
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
Build a method like on the
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