Pages

Patriarchy

In Dictionary of Object Technology: The Definitive Desk Reference, Donald G. Firesmith provides the following definition for the word polymorphism:
n. 1. the ability of a single name to refer to different things having different forms.

Firesmith defines overloading as:

n. any polymorphism whereby the same name is overloaded (i.e., is used for different, but analogous, abstractions).
And he defines global overloading as:
n. any overloading in which the same name is used for abstractions in different contexts or scopes unrelated by inheritance.


From https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html:
You can use a construct called varargs to pass an arbitrary number of values to a method. You use varargs when you don't know how many of a particular type of argument will be passed to the method. It's a shortcut to creating an array manually.

To use varargs, you follow the type of the last parameter by an ellipsis (three dots, ...), then a space, and the parameter name. The method can then be called with any number of that parameter, including none.


/* A social system in which the father is head of the household, having authority over women and children,
 * and in which lineage is traced through the male line.
 *
 *                                                             — https://en.wiktionary.org/wiki/patriarchy
 */
public class Patriarchy
{
    private static void printLineages(String heading, Descendant... lineage)
    {
        System.out.println(heading);
        for (Descendant d : lineage)
            System.out.println("\n" + d.toString());
    }
    private static Descendant[] getLineages(String[] names)
    {
        final int n = names.length;
        final String a = n > 0 ? names[0] : Descendant.UNDEFINED;
        final String b = n > 1 ? names[1] : Descendant.UNDEFINED;
        final String c = n > 2 ? names[2] : Descendant.UNDEFINED;
        Descendant[] bc = { new Son(b, a), new Grandson(c, b, a) };
        return bc;
    }
    public static void main(String args[])
    {
        printLineages("EXAMPLE 1", new JohnSpurgeon());
        System.out.println();
        final String a = "Adam", b = "Cain", c = "Enoch";
        printLineages("EXAMPLE 2", new Father(a), new Son(b, a), new Grandson(c, b, a));
        System.out.println();
        printLineages("EXAMPLE 3", getLineages(args));
    }
}
/* NOTES
 *
 * 1. In addition to declaring methods, interfaces may also define static constants.
 *    Such constants are always static and final; in other words, they are static and
 *    final even if those keywords don't appear before the name of the constant.
 * 2. Methods declared in an interface are public and abstract by default; i.e.,
 *    the keywords public and abstract may be used explicitly or they may be omitted.
 * 3. The name of an interface may be used to specify the type of a variable. This
 *    technique is commonly used when the variable is a parameter. This is an example
 *    of global overloading.
 */
interface Descendant
{
    // public static final String UNDEFINED = "undefined";
    String UNDEFINED = "undefined";

    // public abstract String whoAmI();
    String whoAmI();
    String whoIsMyFather();
    String whoIsMyGrandfather();
}

class JohnSpurgeon implements Descendant
{
    final public String whoAmI()             { return "I am John Spurgeon."; }
    final public String whoIsMyFather()      { return "My father is Paul Spurgeon."; }
    final public String whoIsMyGrandfather() { return "My father's father was Frank Spurgeon."; }
}

class Father implements Descendant
{
    private final String firstInLine;
    protected String self()        { return this.firstInLine; }
    protected String father()      { return Descendant.UNDEFINED; }
    protected String grandfather() { return Descendant.UNDEFINED; }
    public Father(String me)       { this.firstInLine = me; }
    final public String whoAmI()
    {
        return "I am " + this.self() + ".";
    }
    public String whoIsMyFather()
    {
        return "My father, who art in heaven, hallowed be Thy name.";
    }
    final public String whoIsMyGrandfather()
    {
        return "My grandfather is " + this.grandfather() + ".";
    }
    public String toString()
    {
        return whoAmI() + "\n" + whoIsMyFather();
    }
}

class Son extends Father
{
    private final String secondInLine;
    protected String self()   { return secondInLine; }
    protected String father() { return super.self(); }
    public Son(String me, String myFather)
    {
        super(myFather);
        secondInLine = me;
    }
    final public String whoIsMyFather()
    {
        return "My father is " + father() + ".";
    }
    public String toString()
    {
        return whoAmI() + "\n" + whoIsMyFather() + "\n" + whoIsMyGrandfather();
    }
}

class Grandson extends Son
{
    private final String thirdInLine;
    protected final String self()        { return thirdInLine; }
    protected final String father()      { return super.self(); }
    protected final String grandfather() { return super.father(); }
    public Grandson(String me, String myFather, String myGrandfather)
    {
        super(myFather, myGrandfather);
        thirdInLine = me;
    }
}

/* Command-line args: "a" "b" "c"
EXAMPLE 1

JohnSpurgeon@5f205aa

EXAMPLE 2

I am Adam.
My father, who art in heaven, hallowed be Thy name.

I am Cain.
My father is Adam.
My grandfather is undefined.

I am Enoch.
My father is Cain.
My grandfather is Adam.

EXAMPLE 3

I am b.
My father is a.
My grandfather is undefined.

I am c.
My father is b.
My grandfather is a.
*/