Subclassing an abstract class

From the Oracle Java documentation:

An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.

Abstract classes can be useful where multiple classes share similar methods or fields[1]. In some programming scenarios, multiple classes should always implement a common method from a superclass. In such cases, declaring the superclass and common method as abstract will ensure consistent behavior.


Creating and using an abstract class

For this demonstration, I will be using code copied from my Benson project*. In short, Benson is a small project that enables people to control various electronics via voice. When someone speaks to Benson, he attempts to match the spoken words to keywords within a predefined list of queries. Each query should require different keywords and respond differently from one another however, each query must have keywords and responses. This is the quintessential usage case for an abstract class, see the code below*.

public abstract class Query {

    public abstract List<String> getInputs();

    public abstract Response getResponse();
    
}

In the above abstract class, we have two abstract methods. It should be noted that abstract methods cannot have a body. Each potential query that Benson will iterate through will subclass the above Query class. The following code will demonstrate this.

public class Hello extends Query {

    @Override
    public List<String> getInputs() {

        return Arrays.asList("hello", "hey", "hi", "howdy");

    }

    @Override
    public Response getResponse() {

        return new Response("Hello there!");

    }

}

The above code represents a simple extension of the abstract Query class. Notice that both abstract methods defined in the Query class are overridden here and return actual values. Benson will iterate through a list of various subclasses that extend our abstract Query class and use both of the abstract methods to respond to speech. To demonstrate how this is done, review the following code.

List<? extends Query> lexicon = Arrays.asList(new Hello(), 
        new Goodbye());

for (Query query : lexicon) {

    for (String input : query.getInputs()) {

        if (speech.contains(input)) {

            say(query.getResponse());

            return;

        }

    }
    
}

The above code demonstrates how Benson responds to speech. First, we create a list of every subclass we want to include in his lexicon. You will notice the Hello class we discussed earlier is defined here as well as a Goodbye class that was not discussed. When Benson receives spoken text, he iterates through this list of Query subclasses in attempt to find the spoken text defined as an input. If the speech matched an input of a Query subclass, the response is retrieved from the Query and then spoken.


Conclusion

Abstract classes can prove to be very useful for writing reusable code. Subclassing an abstract class in place of using different classes with similar methods may significantly reduce lines of unnecessary code. In my opinion, less code translates into less opportunity for bugs so be sure to ask yourself if you can extend an abstract class whenever you find yourself in need of multiple classes that share methods.


Further reading

A JavaCodeGeek example.

A JavaCoffeeBreak example.

A StackExchange discussion.


References

[1] http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html <Accessed on March 6, 2015>

* All code used in this post is modified from Benson’s source code for simplicity

Instantiate your Fragment by using a static factory method

From the Android developer documentation:

A Fragment represents a behavior or a portion of user interface in an Activity…[y]ou can think of a fragment as a modular section of an activity, which has its own lifecycle, receives its own input events, and which you can add or remove while the activity is running.

Fragments were added in API 11 (Honeycomb)[1] in February of 2011[2] and have become a staple in most applications developed since. Typical usage cases of fragments necessitate dynamic variables to be present when the Fragment is instantiated. The most common method to achieve this is using a static factory method within the Fragment itself.


Using the static factory method

For the sake of simplicity, let’s say you have an Activity (ActivityMain) which adds a Fragment (TextFragment) to a container within the activity’s layout to display a particular String. Since the only job of the TextFragment is to display text, we will most likely call the fragment’s setArguments() method every time we want to use it.

TextFragment textFragment = new TextFragment();
Bundle bundle = new Bundle();
bundle.putString("arg_text", "Hello there!");
textFragment.setArguments(bundle);

There is nothing inherently wrong with using the above method to instantiate the TextFragment; however, let’s add the static factory method to the TextFragment and examine the resulting code that utilizes it.

public class TextFragment extends Fragment {
    
    private static final String ARG_TEXT = "arg_text";

    public static TextFragment newInstance(String text) {

        TextFragment textFragment = new TextFragment();
        Bundle bundle = new Bundle();
        bundle.putString(ARG_TEXT, text);
        textFragment.setArguments(bundle);
        
        return textFragment;
        
    }

}

With the static factory method in place, we can now initialize the TextFragment with the following code:

TextFragment textFragment = TextFragment.newInstance("Hello there!");

The resulting use of the static factory method provides three critical improvements over the first method of instantiating the TextFragment. First, the static factory method reduces code by subsequently increasing code readability. The benefits of this should be self-evident. Second, the static factory method ensures the same key is used to add the text to the Bundle. Although this can be alleviated by using a public static final String as a key, having multiple parameters only increases the potential to accidentally mix up keys and their accompanying parameters. Finally, the static factory method helps prevent mundane code errors such as forgetting to call setArguments(). In this respect, reusing the same code to instantiate a Fragment may significantly reduce the time it takes to debug such issues.


Conclusion

The benefits of using the static factory method to initialize your fragments may not be substantial enough to change your existing code; however, it is my humble opinion that it is in every developers’ best interest to adopt specific coding practices that have the potential to ease his/her workload. Practically speaking, the static factory method just makes more sense.


Further reading

A succinct blog post by Alex Lockwood.

A discussion on StackOverflow.

The Android developer documentation.


References

[1] http://developer.android.com/reference/android/app/Fragment.html <Accessed on February 16, 2015>

[2] http://developer.android.com/reference/android/os/Build.VERSION_CODES.html#HONEYCOMB <Accessed on February 16, 2015>