Search code examples
javafactoryfinal

Java Factory pattern - How to prevent anonymous subclasses


I'm doing a school assignment where I have to implement the Factory pattern. I have come a long way, but there is one last thing I have not been able to get working.

I have the following classes:

//Human.java
package human;
public abstract class Human{
    public static Human create(String namn, String pnr){
        char nastsist_char = pnr.charAt(9); // takes second last char in pnr
        String nastsist_string = Character.toString(nastsist_char);
        float siffra = Float.parseFloat(nastsist_string);   //Converts to float
        if ((siffra % 2) == 0){                 //Checks if even
            return new Woman(namn, pnr);            
        }
        else{
            return new Man(namn, pnr);
        }

    }

}

//Man.java
package human;
class Man extends Human{
    private final String pnr;
    private final String namn;

    protected Man(String n, String p){
        namn = n;
        pnr = p;
    }
    public String toString(){
        return "My name is "+namn+" and I am a man.";
    }   
}

//Woman.java
package human;
class Woman extends Human{
    private final String pnr;
    private final String namn;

    protected Woman(String n, String p){
        namn = n;
        pnr = p;
    }
    public String toString(){
        return "My name is "+namn+" and I am a woman.";
    }

}

I also have a class called Test.java. Here comes my problem: In Test.java, I want to make it impossible to do the following:

Human h = new Human(){};

i.e., to create an anonymous subclass of Human. Unfortunately, this line of code runs just fine, and an anonymous subclass is created. How can I make this line of code unexecutable/uncompilable?

PS. I have already tried making Human final. It was not allowed to combine final with abstract in a class.

EDIT:

So I got the tip to make the Human constructor protected. Here's what it looks like after the change:

//Human.java
package human;
public abstract class Human{
    protected Human(){}

    public static Human create(String name, String idNumber){
        char secondlast_char = idNumber.charAt(9); // takes second last char in pnr
        String secondlast_string = Character.toString(secondlast_char);
        float siffra = Float.parseFloat(secondlast_string); //Converts to float
        if ((siffra % 2) == 0){                 //Checks if even
            return new Woman(name, idNumber);           
        }
        else{
            return new Man(name, idNumber);
        }
    }
}

Unfortunately, I still do not get an error neither when running or compiling the code of Test.java, which by the way looks like this:

import human.*;
public class Test{
    public static void main(String[] args){
        Human h = new Human(){};
    }
}

Solution

  • Add a constructor with the default visibility:

    public abstract class Human {        
        Human(){}    
    }
    

    By default this only allows access to classes within the same package so it is known as "package private".