Very complicated Java HelloWorld app

Posted on

Problem

This program attempts to shows the basic concepts of inheritance and polymorphism. In what ways could the code be modified to better demonstrate those concepts? The interface, abstract class and the class are all in separate files.

Greeting Interface

interface Greeting {
    void sayHello(String greeting, String name);
}

Abstract Hello Class

abstract class Hello {
    String name;
    String greeting;
    public abstract void setName(String name);
    public abstract void setGreeting(String greeting);
    public abstract String getName();
    public abstract String getGreeting();
}

Class that says “Hello”

public class Test extends Hello implements Greeting {
    private String name;
    private String greeting;

    public void setName(String name) {
    this.name = name;
    }
    public void setGreeting(String greeting) {
    this.greeting = greeting;
    }
    public String getName() {
    return name;
    }
    public String getGreeting() {
    return greeting;
    }
    public void sayHello(String g, String n) {
    System.out.print(g + " " + n);
    }
    public static void main(String[] args) {
    Test t = new Test();
    t.setGreeting("Hello");
    t.setName("World!");
    String h = t.getGreeting();
    String w = t.getName();
    t.sayHello(h,w);

    }
}

Solution

Your example implementation is not good enough. It’s not very complicated at all, as you suggest with the title; rather, it is really simple.

The Hello abstract class is not needed. There is no reason why a class (like a WelcomeEmailContentBuilder or something of the sort) should want to extend Hello – something like a WelcomeEmailContentBuilder might already be extending a ContentBuilder or a EmailContentBuilder. You are abusing the is-a relationship.

Consider this rewrite of your code:

interface Greeting {
    void sayHello(String greeting, String name);
}


public class Test implements Greeting {

    public void sayHello(String greeting, String name) {
        System.out.print(greeting + " " + name);
    }

    public static void main(String[] args) {
        Greeting g = new Test();
        g.sayHello("Hello", "World!");
    }

}

This code is just as functional as your original code. But it’s both way shorter and doesn’t muck about with an abstract class that you don’t need. It also makes use of the Greeting interface for a variable – showing off that you can call functions on objects if you only have an interface.

As for making your code actually show off the use of inheritance and polymorphism, that’s up to you to figure out.

As @Pimgd noted, your Hello class doesn’t contribute anything. If you remove it, everything works.

Another problem is that it’s unclear why you would name the primary method of a Greeting to be sayHello. This is particularly confusing since you have a class named Hello. Why not just say?

Why are you instantiating an abstract Hello as Test? The name Hello seems overly concrete for that. And Test doesn’t indicate an extension of Hello to me.

Consider something like

public interface Statement {
    public void say(String name);
}

public abstract class Greeting implements Statement {

    protected final String greeting;

    protected Greeting(String greeting) {
        this.greeting = greeting;
    }

    public String getGreeting() {
        return greeting;
    }

    public void say(String name) {
        System.out.format(greeting, name);
    }

}

public class Hello extends Greeting implements Statement {

    public Hello() {
        super("Hello, %s.");
    }

}

public class Test {

    public static void main(String[] args) {
         Statement hello = new Hello();
         hello.say("World");
    }

}

Now each of the classes does something. If you want to make this clearer, you could add additional greetings or other implementations of Statement.

I also think that this taxonomy fits better. It doesn’t entirely convince me, but then this is a toy problem that could be solved with a one liner. I do think that this better fits the constraints (must say “Hello, World.” and must have an interface and abstract class).

There is probably a better name for Statement that would include the concept of a name parameter. English.SE or ELL.SE might be better suited to help with that.

By making name a parameter of say, we no longer make a Greeting only work for one person. We also avoid breaking thread safety, although this example won’t exhibit that.

I find it rather bizarre that you call getters on an object in order to call a method related to the object. That’s exactly why we have objects, so as to encapsulate that kind of logic. So I prefer this version, that doesn’t require that kind of behavior.

I’d avoid trying to jam a demonstration of setters into this as well. They don’t really fit this model. There’s nothing to set in “Hello, World” except the name, and that really seems too localized.

Leave a Reply

Your email address will not be published. Required fields are marked *