Skip to main content

Java Keywords (Part XXIV): native

Java keyword list abstract continue for new switch assert default goto * package synchronized boolean do if private this break double implements protected throw byte else import public throws case enum instanceof return transient catch extends int short try char final interface static void class finally long strictfp volatile const * float native super while Keyword marked with an asterisk (*) are keywords that, although valid, are not used by programmers. This is the last chapter of the Java Keyword series. This is probably the keyword I have used the least. In my 20 year career as a software developer, I have used this keyword once, and that was to make some addition to legacy code. The keyword native is a method modifier . Basically, it is a keyword that can only be applied to methods. According to the Java Language Specification (JLS), A method that is native is implemented i...

Aggregation and Composition

When determining the relationship between object at design time, it is easy to succumb to the habit of using inheritance; simply because it is easy.  In a language such as C++, it is even easier to do so because the language supports multiple inheritance.

Figure 1: the java.util.List Interface
Assume that Java does not have a Stack (java.util.Stack) class and you need to create a custom stack (call it MyStack).  You could do this in three different ways, but for the purposes of this paper I will discard the creation of the Stack class as shown in the image above.  Therefore, assume that there are only two ways.  The first way is to extend the ArrayList class.  The second way is to include an ArrayList object as a data member.  The first solution uses inheritance to solve the problem.  Remember, inheritance establishes an “is-a” relationship between objects.  Therefore, the relationship between MyStack and ArrayList is incorrect since a stack is not an array list.  The second solution is actually the best.  In fact, one of the rules of effective class design is to favor composition over inheritance.  But, what is composition exactly?  By definition, composition is the act of combining parts to form a whole (or a composite object).  Also, composite means something made up of distinct parts.  Because of this definition, it is said that composition enforces a “has-a” relationship.  For the second solution, this means than MyStack has an ArrayList that it uses to store data.

Figure 2: Association with Dependency

For now, let us assume that we do not know the exact nature of the relationship between MyStack and ArrayList.  In UML, the most generic relationship between two entities is called Association.  Association could be shown as a simple line between two classes or two objects.  Normally, this is done very early during the design phase.  The picture in Figure 2 shows an association relationship illustrating a dependency.  In this case, I cannot implement my stack if I do not have a list to hold my values.  The solid line indicates that it is a class dependency and not an interface.  This notation is also known as a unidirectional association.

Sometimes system designers will not further define association relationships.  This means that the association between entities will be left generic, which causes the developer to make a decision at implementation time which type of relationship will be used.  As I mentioned before, composition should be favored over inheritance.  Most times, this issue could be resolved by simply asking the question “is entity one a type of entity two?”  If the answer is no, then the association relationship will take the shape of either an aggregation or composition.  If the answer is yes, then the association relationship will take the shape of inheritance.  The rest of this handout will discuss aggregation and composition.

Aggregation and composition are highly debatable topics in UML.  We already defined composition as a “has-a” relationship.  The connotation of the use of the verb “has” implies possession or ownership.  On the other hand, an aggregation relationship in UML is defined as a “part-of” relationship; which has no connotations of ownership whatsoever.

Figure 3: Aggregation

Aggregation is a more specialized form of association.  In UML, the hollowed diamond goes to the object or class containing the reference to the other object in the relationship.  In this case, MyStack contains an ArrayList reference (just one as illustrated by the multiplicity value of 1).  This relationship establishes that the ArrayList reference is part of MyStack.  However, that reference could be shared by other instances of MyStack.

Figure 4: Composition

One could argue that composition is an even more specialized form of aggregation.  Not only an entity is part of another entity, but it is an exclusive part of the other.  For instance, a car has an engine. The relationship between an instance of car and an instance of engine is exclusive because the engine is not shared with other instances of car.  In this case, it makes sense to say that a car has an engine.  The “no sharing” rule is key to composition.

Another assumption you can make between aggregation and composition has to do with object destruction.  In the case of MyStack, if we designed MyStack to contain an exclusive instance of ArrayList, then it is safe to say that when invoking the MyStack destructor (know that Java does not have class destructors as C++) it is safe to invoke the ArrayList destructor.  This is because the specific instance of ArrayList is not shared.  However, because in an aggregation relationship the aggregated object is shared, it is not safe to invoke its destructor from the entity containing the reference.  In a language such as Java, the garbage collection mechanism is supposed to figure out when objects are no longer referenced in a program and reclaim resources used by such unused objects.  In C++, the responsibility of when to reclaim such resources is on the programmer.

It is really difficult to know when aggregation is more appropriate than composition or vice versa.  In my opinion, it is more natural to use composition.  However, computer resources are not infinite.  So, it is a good programming practice to determine during the design phase how objects are going to be used.  For instance, do I want my array list to be a shared resource?  Games often include lists of players’ stats.  The only way to guarantee that every player sees the same information is if the same list is shared.  For an implementation such as this one, it is perhaps best if aggregation is used.  The same could be achieved using composition.  However, it is very likely that the implementation will be slower, more error prone, etc (more ineffective).

In conclusion, composition should be favored over inheritance; especially in a language such as Java where classes could only have one immediate super-class. As far as aggregation vs. composition, the rules are not so easily defined.  Composition tends to be more natural.  Aggregation, when implemented properly, makes more effective use of computer resources because the aggregate object is shared.   However, this could lead to memory management issues in languages such as C++ (without an automatic garbage collection mechanism).  In contrast, components of a composite object could be destroyed safely when the composite object is destroyed.

Comments

Popular posts from this blog

Implementing Interfaces with Java Records

If you have not read my article on Java records and do not know about this topic, please read my blog titled " Customizing Java Records " first and then come back to this one. Now that you know how to customize Java records, implementing an interface using Java records should be very easy to understand. If you don't know about interfaces in Java, you can read more on my article about interfaces. The recipe for implementing an interface is simply an expansion of what you learned in my previous blog on how to customize a Java record. Following our Rectangle example, let's create an interface with the same two methods we used before. public interface Shape { double area(); double perimeter(); } Now, let's further customize the previous example by doing two things: Add implements Shape at the end of the record declaration (after the record constructor), and Add @Override to the existing methods to ensure these methods com...

Customizing Java Records

If you have not read my article on Java records and do not know about this topic, please read my blog titled " Java Keywords Addendum: The Java Record " first and then come back to this one. What is a customization of a record? A customization of a record is simply the addition of code inside the body of the class. Before proceeding further, let's recap important aspects of a Java Record: Java records are immutable Because of item 1 above, you cannot add new fields unless defined in the record constructor Java records already override: Object#equals(Object) and Object#hashCode() , and then override Object#toString() You could redefine overridden methods as part of your customization if you would like. For example, if you want a fancier implementation of the Object#toString() method, you could do so. Let's look at our first customization example. Using the example from my previous blog, public record Student(...

Object-Oriented Programming Basics: What is in a Class?

EDITORIAL NOTE : This article was published briefly back in 2016 and quickly set back to draft because I wasn't happy with its contents. It is a shame that it was taking me three years to revisit this topic and work on a new and improved version. At least, I'm hoping it will be to the liking you the reader. Keep in mind that the opening paragraph will still read as if I just wrote it for my (former) students at Texas Wesleyan. I started working on lecture on the topic of Object-Oriented (OO) Programming by gathering some material, old and new, when I realized this might be good and simple post for my second attempt at blogging. To be completely honest, in the 8 hours I spent collecting information and preparing material for this week's lecture, I realized I still made some of the mistakes I am about to blog about. I am actually hoping I can write a series of postings regarding Object-Oriented Programming (OOP). But to do so, I must start from the very beginning. ...