Reputation: 799
I have a parent class containing a struct-like static nested class. The nested class must be public, as it should be returned to other classes where its contents are acted upon. However, only the parent class and its subclasses should be able to instantiate the nested class, as they know how to define its contents. All classes shown below are in different packages.
public abstract class Parent
{
public static class Data
{
public final String data1
...
public Data(String d1, ...)
{
data1 = d1;
...
}
}
public abstract Data getData();
}
public final class Subclass extends Parent
{
@Override
public Data getData()
{
return new Data(.....);
}
}
public class SomeOtherClass
{
public void someMethod()
{
final Data d = new Subclass().getData();
System.out.println(d.data1);
}
}
Declaring the Data
class protected
would stop getData()
from working properly. Decreasing the access modifier on the constructor of Data
would prevent subclasses of Parent
from working properly. What I want is something like protected-by-parent
, which I am guessing does not exist in Java.
Is there a suitable workaround? One possibility I can see is creating a protected
method in Parent
that effectively mirrors, calls, and returns from the constructor of Data
(which would be made private
). This however seems a bit messy; does anybody know of a better way/design?
Upvotes: 5
Views: 1036
Reputation: 394146
A better solution would be to make the nested class protected
, and make it implement a public
interface. Only the interface will be exposed to outside classes, and the nested class itself will remain an implementation detail.
public abstract class Parent
{
public interface Data {
public String getData1();
}
protected static class DataImpl implements Data
{
private final String data1;
...
protected DataImpl(String d1, ...)
{
data1 = d1;
...
}
public String getData1(){
return data1;
}
}
public abstract Data getData();
}
public final class Subclass extends Parent
{
@Override
public Data getData()
{
return new DataImpl(.....);
}
}
public class SomeOtherClass
{
public void someMethod()
{
final Data d = new Subclass().getData();
System.out.println(d.getData1());
}
}
Upvotes: 3
Reputation: 31299
You cannot make a constructor of a static member class protected
for the subclasses of the outer class. That expressiveness doesn't directly exist in the Java language.
But, you can make the constructor of the static member class Data
private
- in that case, the outer class can still access it. And the outer class can define a protected factory method that invokes the Data
constructor - by making it protected
, it is only accessible to Parent itself, subclasses, and all classes in the same package (as is always the case for the protected
modifier)
public abstract class Parent
{
protected static Data createData(String d1, ...) {
return new Data(d1, ...);
}
public static class Data
{
public final String data1
...
private Data(String d1, ...)
{
data1 = d1;
...
}
}
public abstract Data getData();
}
Upvotes: 3