Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum styled factory as inner Enum in Java

I tried to implement an Enum styled factory pattern as inner Enum, but it didn't work. Is there any solution without separating inner Enum into a new file? In other words, is it possible of inner Enum styled factory pattern?

The code is below.

public class SampleParent {

    private class InnerChild { }
    private class InnerChildA extends InnerChild { }
    private class InnerChildB extends InnerChild { }
    private class InnerChildC extends InnerChild { }

    enum InnerChildEnum {
        CHILD_A {
            @Override
                public InnerChild getInstance() {
                    return new InnerChildA();  // compile error
                }
        },
        CHILD_B {
            @Override
                public InnerChild getInstance() {
                    return new SampleParent.InnerChildB();  // compile error
                }
        },
        CHILD_C {
            @Override
                public InnerChild getInstance() {
                    return SampleParent.new InnerChildC();  // compile error
                }
        },
        ;

        public abstract InnerChild getInstance();
    }

    private static class InnerChildFactoryEnumStyled {
        public static InnerChild getInnerChild(InnerChildEnum child) {
            return child.getInstance();
        }
    }


    public static void main(String[] args) {

        // I want to write this way
        InnerChild child = InnerChildFactoryEnumStyled.getInnerChild(InnerChildEnum.CHILD_A);
    }
}

The compile error message is below

$ javac SampleParent.java 
SampleParent.java:12: error: non-static variable this cannot be referenced from a static context
                return new InnerChildA();
                       ^
SampleParent.java:18: error: non-static variable this cannot be referenced from a static context
                return new SampleParent.InnerChildB();
                       ^
SampleParent.java:24: error: cannot find symbol
                return SampleParent.new InnerChildC();
                       ^
  symbol: variable SampleParent
3 errors
like image 217
forte916 Avatar asked Mar 23 '17 14:03

forte916


2 Answers

Your inner classes are not static so they must refer to an instance of the enclosing class SampleParent. Change your class declarations to

private static class InnerChild { }
private static class InnerChildA extends InnerChild { }
private static class InnerChildB extends InnerChild { }
private static class InnerChildC extends InnerChild { }

and you can e. g. return new InnerChildA(); in your enum.

like image 105
Stefan Warminski Avatar answered Sep 18 '22 04:09

Stefan Warminski


To instantiate a no static inner class(InnerChildA, InnerChildB, etc...), you need to qualify the instantiation with an instance of the enclosing type (SampleParent). You have to do something like that : new ExternalClass().new InternalClass()

In your case you could declare and instance a static SampleParent instance in the InnerChildEnum enum and reuse it in each implemented getInstance() method of the enum values declaration.

private class InnerChild {
}

private class InnerChildA extends InnerChild {
}

private class InnerChildB extends InnerChild {
}

private class InnerChildC extends InnerChild {
}

enum InnerChildEnum {

    CHILD_A {
        @Override
        public InnerChild getInstance() {
            return sampleParent.new InnerChildA();
        }
    },
    CHILD_B {
        @Override
        public InnerChild getInstance() {

            return sampleParent.new InnerChildB(); // compile error
        }
    },
    CHILD_C {
        @Override
        public InnerChild getInstance() {
            return sampleParent.new InnerChildC();
        }
    };

    private static SampleParent sampleParent = new SampleParent();

    public abstract InnerChild getInstance();
}
like image 42
davidxxx Avatar answered Sep 22 '22 04:09

davidxxx