C# and VB Object-Oriented Programming in Visual Studio .NET
Overriding and overloading
One of the harder concepts to grasp in the object-oriented paradigm is inheritance behavior overriding and overloading. Overloading is simply using the same behavior to treat different kinds of data. For example, a MathHelper class might have a behavior that allows it to do something with two integers, for example, add them. If the MathHelper class were to be extended to work with floating point numbers, the same behavior could be reused with a different input data type.
Overriding is the hardest of the two terms to master. The basic premise is that if you are building a shopping cart for a Web site, the Book class (one of the kinds of items you are selling) should derive from a more general concept, probably a CatalogItem, and the subclasses should never be used directly.
This kind of abstraction allows you to build most of your system using the methods exposed by CatalogItem because every CatalogItem should have a price, a description, and a label. The system doesn't know that when it's getting the price for a CatalogItem; the call is actually delegated to the subclass Book, which is calling Amazon.com to retrieve the current price. If the system is getting the description for a CD, it still reads the description attribute from the CatalogItem, but the call is once again delegated to the CD class, which contacts CDDB.com to retrieve the last album review.
It's true that this could be implemented using interfaces, as seen earlier. But overriding allows you to use one extra trick, which you can't do using interfaces. It lets you reuse the parent's default behavior. For example, a Rectangle class, which is a Shape, has for a subclass ShadedRectangle. When the system calls the draw behavior, the call is delegated to the most derived class, hence ShadedRectangle. It can simply call the draw behavior of its parent (which will draw just a rectangle) and then finish by drawing the actual shadow.
The following UML diagram represents overriding and overloading. The code that follows implements the diagram.
VB.NET Code Snippet | C# Code Snippet |
Public Class Person Public birthDay As DateTime Public Sub SetBirthDay(ByVal year As Integer, ByVal month As Integer, ByVal day As Integer) SetBirthDay(New DateTime(year, month, day)) End Sub Public Overridable Sub SetBirthDay(ByVal datetime As DateTime) birthDay = datetime End Sub End Class Public Class Customer Inherits Person Public Overloads Sub SetBirthDay(ByVal datetime As DateTime) MyBase.SetBirthDay(datetime) Calendar.Instance().AddEvent("Customer Birthday", datetime, Me) End Sub End Class |
public class Person { public DateTime birthDay; public void SetBirthDay(int year, int month, int day) { SetBirthDay(new DateTime(year, month, day)); } public virtual void SetBirthDay(DateTime date) { birthDay = date; } } public class Customer : Person { public override void SetBirthDay(DateTime date) { base.SetBirthDay(date); Calendar.Instance().AddEvent("Customer BirthDay", date, this); } } |
Aggregation and composition
Aggregation and composition are two kinds of relationships that exist between classes. They form a whole-part relationship that you can use to decompose objects into more manageable entities. For example, a class named Airplane would have two Wings. The difference between aggregation and composition is very simple although sometimes difficult to identify. Aggregation means that the Wing class can exist and be used independently of the Airplane class. Aggregation is represented by a non-filled lozenge at the end of the link. Composition is a stronger relationship, in which the part has no meaning or usage outside of the relationship. It is represented by a filled lozenge at the end of the link.
Some of these associations can be identified by using the "has a" phrase. Take, for example, a Vehicle class has an Engine. More specifically, the Vehicle has one Engine, and this extra information is usually written as a numerical identifier on the proper side of the link between the classes on the UML diagram. You can use the identifiers as a hint on how to implement the relationship when you develop the code. For example, if an Airplane has two Wings, the Airplane class could have an attribute that is an array of two Wing classes. If the numerical identifier is a star "*", you could implement the association using the System.Collections.ArrayList object, which supports a variable number of items.
The following UML diagram illustrates the concepts of aggregation and composition. The snippet of code that follows implements the diagram.
VB.NET Code Snippet | C# Code Snippet |
Public Class Order Protected orderItems As ArrayList Protected shippingAddress As Address Protected Class OrderStatus Public isShipped As Boolean Public isPaid As Boolean End Class Protected status As OrderStatus End Class |
public class Order { protected ArrayList orderItems; protected Address shippingAddress; protected class OrderStatus { public bool isShipped; public bool isPaid; } protected OrderStatus status; } |
Other associations
Sometimes, when looking at a static class UML diagram, you will simply see links between classes and qualifiers attached to them. This kind of diagram usually exists to express the relationships between the objects. For example, a class named TicketGenerator could be linked to a class named GeneralAdmissionTicket by the Creates qualifier. This is a hint and expresses the fact that GeneralAdmissionTicket class instances are probably created by a behavior of the TicketGenerator class.
Page 3 of 4
This article was originally published on September 18, 2002