I have been using delegation pattern to wrap an object created by a factory in a 3rd party library. Recently, the library added a protected method in the base class and my wrapper class doesn't work any longer. Does anyone have a good solution without resorting to reflection?
This is in 3rd party library and in their package,
public class Base {
public void foo();
protected void bar(); // Newly added
}
This is in my own package,
public class MyWrapper extends Base {
private Base delegate;
public MyWrapper(Base delegate) {
this.delegate = delegate;
}
public void foo() {
delegate.foo()
}
protected void bar() {
// Don't know what to do
}
}
EDIT: My original post wasn't clear. These 2 classes are in different packages.
To answer the question why I need delegation. This is a typical use-case of Delegation/Wrapper pattern and I can't show it here in a few lines of code. The library exposes Base class but the actual object from their factory is a derived class of Base. The actual class changes depending on configuration. So I don't know what delegate is. Therefore straight inheritance pattern doesn't work here.
Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N
protected has package access too, do you see any specific issue with this:
class Base {
public void foo(){};
protected void bar(){}; // Newly added
}
class MyWrapper {
private Base delegate;
public MyWrapper(Base delegate) {
this.delegate = delegate;
}
public void foo() {
delegate.foo();
}
protected void bar() {
// Don't know what to do
delegate.bar(); //since its in same package, it can be referenced, do you expect compile time error?
}
}
Further while using delegator pattern why wrapper class extends Base class, I don't see specific need since you already have an instance of Base. To me it seems more of an decorator.
You don't need (or shouldn't?) delegate that bar method.
If the library defined a protected method. It doesn't want user (of course in different package) to invoke that method, unless creating subclass of that type. You are trying to break the rule.
If you want to do it, there is way, you create a subtype of Base,say SubBase, you create object of SubBase instead of Base, then pass subBase to your wrapper. then you could in your wrapper bar() method write delegate.bar() In this way, the SubBase is actually the delegate, or to say your wrapper is delegating SubBase not Base
I think you know what I mean, so I just don't type example codes, only this line I guess it is enough:
//Wrapper
private SubBase delegate;
You see the wrapper is not necessary any longer if you have SubBase. You could even define a public void pubBar() in your SubBase, and there you call this.bar(). in this way all objects of SubBase have access to the protected method (via pubBar()), no matter from which package
I'm using Spring for injecting in Wrapper the "Base delegate" from another module and for getting the delegate i'm using a pojo factory.
<bean id="interfaceDelegate" factory-bean="DelegatePojoFactory"
factory-method="getMyDelegateInstance">
<constructor-arg index="0">
<value>OnLine</value>
</constructor-arg>
</bean>
<bean id="wrapper" class="path.Wrapper">
<property name="delegate" ref="interfaceDelegate"></property>
</bean>
I get the impression that the Base class is either an interface or an abstract class. If so, you must implement the bar() method, for example by using any of the three methods listed below.
Side note, if Base is a normal class, you do not have do anything (a call to an instance of MyWrapper.bar() will actually result in a call to Base.bar().
Delegate to the parent object
This is usually a good idea if the bar() method is used as a callback in the 3rd party API:
#Override
protected void bar() {
delegate.bar();
}
Do nothing
Just added an empty method to avoid compile errors:
#Override
protected void bar() {
// silently ignored
}
Throw an exception
Violently prevent any usage of the new method:
#Override
protected void bar() {
throw new UnsupportedOperationException("not implemented");
}
As a side note, a more robust construction is to prefer composition over inheritance to decouple your implementation from the 3rd party implementation, e.g.
public class MyWrapper { // does not extend Base
private Base delegate;
public MyWrapper(Base delegate) {
this.delegate = delegate;
}
public void foo() {
delegate.foo()
}
// does not have to implement bar()
}
If you don't need your delegator to be an actual instance of the base class, you can simply remove that relation:
public class MyWrapper {
private Base delegate;
public MyWrapper(Base delegate) {
this.delegate = delegate;
}
public void foo() {
delegate.foo()
}
}
Whether that works for you is highly dependent on your other code, and your needs aren't completely clear to me right now.
If the library defines an interface providing the public method which is implemented by the abstract base class, you could sensibly implement that interface without inheriting from the abstract base class, which might also satisfy your needs.
Related
I'm curious how this all works. I have an interface, let's call it A. When I look at A, it has most of the methods I need, but not all, and I don't have control over interface A, so I extend it with interface B which implements the 1 or whatever number of methods that I need on top of A.
public interface B extends A {
String doSomethingFun(String blah);
}
A has an implementation class called Client. In just a second I'm going to create my own implementation class of B called MyDefaultClient.
I then create a concrete class that implements B, like this:
#Component
public class MyDefaultClient implements B {
private A myClient;
#Autowired
public MyDefaultClient(A myClient) {
this.myClient = myClient;
}
#Override
public String doSomethingFun(String filename) {
// custom business logic
}
#Override
public String serviceName() {
return myClient.serviceName();
}
#Override
public void close() {
myClient.close();
}
}
serviceName() and close() are methods that A forces its implementors to implement. There are other methods though that have default implementations that aren't forcing me to implement them, I assume simply because they have default implementations.
At this point I have a concrete class that I can instantiate in other places and call all of both A and B's methods on it. But is that only because in the interface there are default implementations for these methods, like this?
default Blah someMethodInA(String thing) {
throw new UnsupportedOperationException();
}
If I use this code and call myDefaultClient.doSomethingFun("hello") I'm pretty certain that will do the thing I want it to do. But what about if I call myDefaultClient.someMethodInA()? Will it call the implemented method in Client, which is A's implementor? Or will it fall on the floor and complain with an UnsupportedOperationException? If the latter, is there any way I can structure this so that I can call all of A's methods from B's implementor?
If you want MyDefaultClient to inherit implementations from Client, then it has to extend Client, like this:
class MyDefaultClient extends Client implements B
{
...
}
Then, if Client implements A, you will only have to provide implementations for the new methods that B adds.
or... you can continue your current pattern and explicitly delegate all the calls you want to a field of type A, but you will have to do them all explicitly, even the methods with default implementations. The default implementations will continue the throw exceptions if you don't override them.
An interface can have any number of default methods. Check this for more details. Given below is an example to demonstrate how default methods and extending an interface work:
public interface InterfaceA {
public void toBeImplementedA();
default void hello() {
System.out.println("Hello");
}
default void hi() {
System.out.println("Hi");
}
}
public interface InterfaceB extends InterfaceA {
public void toBeImplementedB();
}
public class AnImplClass implements InterfaceB {
#Override
public void toBeImplementedA() {
System.out.println("toBeImplementedA");
}
#Override
public void toBeImplementedB() {
System.out.println("toBeImplementedB");
}
}
public class Main {
public static void main(String[] args) {
InterfaceB obj = new AnImplClass();
obj.toBeImplementedA();
obj.toBeImplementedB();
obj.hello();
obj.hi();
}
}
Output:
toBeImplementedA
toBeImplementedB
Hello
Hi
Feel free to comment in case of any doubt.
Interfaces can contain default methods. These were added to Java so that an interface could be updated without forcing implementing code to be rewritten.¹
Default methods provide an implementation if your implementing class does not implement them.
When you call methods on an object, the overridden method is always called.
Any other implementations in the super classes / interfaces are used when there is a lack of implementation.
Even if you refer to MyDefaultClient as A,
A myImplementation = new MyDefaultClient();
Under the hood myImplementation is still an instance of MyDefaultClient even though the code views it as A. Therefore your overriden method will be used when doSomethingFun is called.
#Override
public String doSomethingFun(String filename) {
// custom business logic
}
¹ Source: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
Which access modifier, in an abstract class, do I have to use for a method,
so the subclasses can decide whether it should be public or not? Is it possible to "override" a modifier in Java or not?
public abstract class A {
??? void method();
}
public class B extends A {
#Override
public void method(){
// TODO
}
}
public class C extends B {
#Override
private void method(){
// TODO
}
}
I know that there will be a problem with static binding, if
someone calls:
// Will work
A foo = new B()
foo.method();
// Compiler ?
A foo = new C();
foo.method();
But maybe there is another way. How I can achieve that?
It is possible to relax the restriction, but not to make it more restrictive:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method(){ // OK
}
}
public class C extends A {
#Override
private void method(){ // not allowed
}
}
Making the original method private won't work either, since such method isn't visible in subclasses and therefore cannot be overriden.
I would recommend using interfaces to selectively expose or hide the method:
public interface WithMethod {
// other methods
void method();
}
public interface WithoutMethod {
// other methods
// no 'method()'
}
public abstract class A {
protected void method();
}
public class B extends A implements WithMethod {
#Override
public void method(){
//TODO
}
}
public class C extends B implements WithoutMethod {
// no 'method()'
}
... then only work with the instances through the interfaces.
When overriding methods, you can only change the modifier to a wider one, not vice versa. For example this code would be valid:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method() { }
}
However, if you try to narrow down the visibility, you'd get a compile-time error:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
private void method() {}
}
For your case, I'd suggest to make C not implementing A, as A's abstraction implies that there's a non-private method():
public class C {
private void method(){
//TODO
}
}
Another option is to make the method() implementation in C throwing a RuntimeException:
public class C extends A {
#Override
public void method(){
throw new UnsupportedOperationException("C doesn't support callbacks to method()");
}
}
What you are asking for is not possible for very good reasons.
The Liskov substitution principle basically says: a class S is a subclass of another class T only then, when you can replace any occurrence of some "T object" with some "S object" - without noticing.
If you would allow that S is reducing a public method to private, then you can't do that any more. Because all of a sudden, that method that could be called while using some T ... isn't available any more to be called on S.
Long story short: inheritance is not something that simply falls out of the sky. It is a property of classes that you as the programmer are responsible for. In other words: inheritance means more than just writing down "class S extends T" in your source code!
This is impossible because of the polymorphism. Consider the following. You have the method in class A with some access modifier which is not private. Why not private? Because if it was private, then no other class could even know of its existence. So it has to be something else, and that something else must be accessible from somewhere.
Now let's suppose that you pass an instance of class C to somewhere. But you upcast it to A beforehand, and so you end up having this code somewhere:
void somewhereMethod(A instance) {
instance.method(); // Ouch! Calling a private method on class C.
}
One nice example how this got broken is QSaveFile in Qt. Unlike Java, C++ actually allows to lower access privileges. So they did just that, forbidding the close() method. What they ended up with is a QIODevice subclass that is not really a QIODevice any more. If you pass a pointer to QSaveFile to some method accepting QIODevice*, they can still call close() because it's public in QIODevice. They “fixed” this by making QSaveFile::close() (which is private) call abort(), so if you do something like that, your program immediately crashes. Not a very nice “solution”, but there is no better one. And it's just an example of bad OO design. That's why Java doesn't allow it.
Edit
Not that I missed that your class is abstract, but I also missed the fact that B extends C, not A. This way what you want to do is completely impossible. If the method is public in B, it will be public in all subclasses too. The only thing you can do is document that it shouldn't be called and maybe override it to throw UnsupportedOperationException. But that would lead to the same problems as with QSaveFile. Remember that users of your class may not even know that it's an instance of C so they won't even have a chance to read its documentation.
Overall it's just a very bad idea OO-wise. Perhaps you should ask another question about the exact problem you're trying to solve with this hierarchy, and maybe you'll get some decent advises on how to do it properly.
Here is a part of the #Override contract.
The answer is : there isn't any possibility to achieve what you have.
The access level cannot be more restrictive than the overridden
method's access level. For example: if the superclass method is
declared public then the overridding method in the sub class cannot be
either private or protected.
This is not a problem concerning abstract classes only but all classes and methods.
THEORY:
You have the determined modifiers order:
public <- protected <- default-access X<- private
When you override the method, you can increase, but not decrease the modifier level. For example,
public -> []
protected -> [public]
default-access -> [public, default-access]
private -> []
PRACTICE:
In your case, you cannot turn ??? into some modifier, because private is the lowest modifier and private class members are not inherited.
I have the following situation:
A parent class has a function that depends on a constant. But the only valid place to define that constant is in subclasses (parent class cannot define the constant's value, but it can be used with the constant undefined in 99% of use cases - the constant is a default to use if a specific configuration element is missing).
However, I would like to enforce that any child class inheriting from that parent class must define the value for the constant, since any child classes have to be able to use the other 1% of functionality.
What is the best practice to implement this enforcement in Java, ideally at compile time? (clearly, at runtime, I can simply check if the constant is null/empty in the method using it).
My own solution was to implement a value-getter for the constant as an abstract method in the parent class, and call that in combination with the real setter in the constructor; something like this:
public class HelperClass1 {
private String myConstant;
public void setMyConstant() {} // implemented obviousy
public void myMethod() { // Called from ParentClass's methods
// Do something useful with myConstant
}
}
import HelperClass1;
public abstract class ParentClass {
ParentClass() {
HelperClass1.setMyConstant( getMyConstantValue() );
}
public abstract void getMyConstantValue();
}
public class ChildClass1 extends ParentClass {
public void getMyConstantValue() { return "BUZZ"; }
}
public class ChildClass2 extends ParentClass {
} // Fails to compile without getMyConstantValue()
However, (a) This implementation has a problem (I can't use ParentClass itself, since it's now abstract) without subclassing; and (b) since I'm not a Java developer, I'm afraid that this isn't the best or the most elegant solution. So I'd like to know if there's a best practices approach that improves on what I implemented.
Provide two constructors for the parent class:
One is a protected constructor which takes the constant as an argument.
The other is private constructor which can construct instances of the parent class without setting the constant.
Provide a factory method for the parent class which can call the private no-constant constructor.
Classes that want to get an instance of the parent class can call the factory method. But child classes that want to inherit from the parent class have to call the protected constructer, which can validate that a valid constant was passed.
public class ParentClass {
private final SomeClass myConstant;
protected ParentClass(SomeClass aConstant) {
if (null == aConstant) {
throw new IllegalArgumentException("...");
}
myConstant = aConstant;
}
private ParentClass() {
myConstant = null;
}
public static ParentClass getInstance() {
return new ParentClass();
}
}
public class ChildClass {
public ChildClass() {
super(new SomeClass(42));
}
}
This isn't perfect. Someone could write a child class that passes a bad constant to the superclass constructor, and it wouldn't actually fail until some code tried to construct an instance of the child class.
I know that an interface must be public. However, I don't want that.
I want my implemented methods to only be accessible from their own package, so I want my implemented methods to be protected.
The problem is I can't make the interface or the implemented methods protected.
What is a work around? Is there a design pattern that pertains to this problem?
From the Java guide, an abstract class wouldn't do the job either.
read this.
"The public access specifier indicates that the interface can be used by any class in any package. If you do not specify that the interface is public, your interface will be accessible only to classes defined in the same package as the interface."
Is that what you want?
You class can use package protection and still implement an interface:
class Foo implements Runnable
{
public void run()
{
}
}
If you want some methods to be protected / package and others not, it sounds like your classes have more than one responsibility, and should be split into multiple.
Edit after reading comments to this and other responses:
If your are somehow thinking that the visibility of a method affects the ability to invoke that method, think again. Without going to extremes, you cannot prevent someone from using reflection to identify your class' methods and invoke them. However, this is a non-issue: unless someone is trying to crack your code, they're not going to invoke random methods.
Instead, think of private / protected methods as defining a contract for subclasses, and use interfaces to define the contract with the outside world.
Oh, and to the person who decided my example should use K&R bracing: if it's specified in the Terms of Service, sure. Otherwise, can't you find anything better to do with your time?
When I have butted up against this I use a package accessible inner or nested class to implement the interface, pushing the implemented method out of the public class.
Usually it's because I have a class with a specific public API which must implement something else to get it's job done (quite often because the something else was a callback disguised as an interface <grin>) - this happens a lot with things like Comparable. I don't want the public API polluted with the (forced public) interface implementation.
Hope this helps.
Also, if you truly want the methods accessed only by the package, you don't want the protected scope specifier, you want the default (omitted) scope specifier. Using protected will, of course, allow subclasses to see the methods.
BTW, I think that the reason interface methods are inferred to be public is because it is very much the exception to have an interface which is only implemented by classes in the same package; they are very much most often invoked by something in another package, which means they need to be public.
This question is based on a wrong statement:
I know that an interface must be public
Not really, you can have interfaces with default access modifier.
The problem is I can't make the interface or the implemented methods protected
Here it is:
C:\oreyes\cosas\java\interfaces>type a\*.java
a\Inter.java
package a;
interface Inter {
public void face();
}
a\Face.java
package a;
class Face implements Inter {
public void face() {
System.out.println( "face" );
}
}
C:\oreyes\cosas\java\interfaces>type b\*.java
b\Test.java
package b;
import a.Inter;
import a.Face;
public class Test {
public static void main( String [] args ) {
Inter inter = new Face();
inter.face();
}
}
C:\oreyes\cosas\java\interfaces>javac -d . a\*.java b\Test.java
b\Test.java:2: a.Inter is not public in a; cannot be accessed from outside package
import a.Inter;
^
b\Test.java:3: a.Face is not public in a; cannot be accessed from outside package
import a.Face;
^
b\Test.java:7: cannot find symbol
symbol : class Inter
location: class b.Test
Inter inter = new Face();
^
b\Test.java:7: cannot find symbol
symbol : class Face
location: class b.Test
Inter inter = new Face();
^
4 errors
C:\oreyes\cosas\java\interfaces>
Hence, achieving what you wanted, prevent interface and class usage outside of the package.
Here's how it could be done using abstract classes.
The only inconvenient is that it makes you "subclass".
As per the java guide, you should follow that advice "most" of the times, but I think in this situation it will be ok.
public abstract class Ab {
protected abstract void method();
abstract void otherMethod();
public static void main( String [] args ) {
Ab a = new AbImpl();
a.method();
a.otherMethod();
}
}
class AbImpl extends Ab {
protected void method(){
System.out.println( "method invoked from: " + this.getClass().getName() );
}
void otherMethod(){
System.out.println("This time \"default\" access from: " + this.getClass().getName() );
}
}
Here's another solution, inspired by the C++ Pimpl idiom.
If you want to implement an interface, but don't want that implementation to be public, you can create a composed object of an anonymous inner class that implements the interface.
Here's an example. Let's say you have this interface:
public interface Iface {
public void doSomething();
}
You create an object of the Iface type, and put your implementation in there:
public class IfaceUser {
private int someValue;
// Here's our implementor
private Iface impl = new Iface() {
public void doSomething() {
someValue++;
}
};
}
Whenever you need to invoke doSomething(), you invoke it on your composed impl object.
I just came across this trying to build a protected method with the intention of it only being used in a test case. I wanted to delete test data that I had stuffed into a DB table. In any case I was inspired by #Karl Giesing's post. Unfortunately it did not work. I did figure a way to make it work using a protected inner class.
The interface:
package foo;
interface SomeProtectedFoo {
int doSomeFoo();
}
Then the inner class defined as protected in public class:
package foo;
public class MyFoo implements SomePublicFoo {
// public stuff
protected class ProtectedFoo implements SomeProtectedFoo {
public int doSomeFoo() { ... }
}
protected ProtectedFoo pFoo;
protected ProtectedFoo gimmeFoo() {
return new ProtectedFoo();
}
}
You can then access the protected method only from other classes in the same package, as my test code was as show:
package foo;
public class FooTest {
MyFoo myFoo = new MyFoo();
void doProtectedFoo() {
myFoo.pFoo = myFoo.gimmeFoo();
myFoo.pFoo.doSomeFoo();
}
}
A little late for the original poster, but hey, I just found it. :D
You can go with encapsulation instead of inheritance.
That is, create your class (which won't inherit anything) and in it, have an instance of the object you want to extend.
Then you can expose only what you want.
The obvious disadvantage of this is that you must explicitly pass-through methods for everything you want exposed. And it won't be a subclass...
I would just create an abstract class. There is no harm in it.
With an interface you want to define methods that can be exposed by a variety of implementing classes.
Having an interface with protected methods just wouldn't serve that purpose.
I am guessing your problem can be solved by redesigning your class hierarchy.
One way to get around this is (depending on the situation) to just make an anonymous inner class that implements the interface that has protected or private scope. For example:
public class Foo {
interface Callback {
void hiddenMethod();
}
public Foo(Callback callback) {
}
}
Then in the user of Foo:
public class Bar {
private Foo.Callback callback = new Foo.Callback() {
#Override public void hiddenMethod() { ... }
};
private Foo foo = new Foo(callback);
}
This saves you from having the following:
public class Bar implements Foo.Callback {
private Foo foo = new Foo(this);
// uh-oh! the method is public!
#Override public void hiddenMethod() { ... }
}
I think u can use it now with Java 9 release. From the openJdk notes for Java 9,
Support for private methods in interfaces was briefly in consideration
for inclusion in Java SE 8 as part of the effort to add support for
Lambda Expressions, but was withdrawn to enable better focus on higher
priority tasks for Java SE 8. It is now proposed that support for
private interface methods be undertaken thereby enabling non abstract
methods of an interface to share code between them.
refer https://bugs.openjdk.java.net/browse/JDK-8071453
Static method M returns an object implementing interface A:
interface A { ... }
static A M() { ... }
Within M I would like to construct an object of type B and return that, given that B implements A:
class B implements A { ... }
I do not want client code to know anything about how B is implemented, I would prefer for B not to be a static class, B must be immutable and there could be different B handed to different clients. I want to prevent instantiation of B outside method M at all costs (short of reflection, as one user commented).
How can I achieve the above? Where and how should I implement B? Could you please provide a short code example?
My main problem is: how can I have "different Bs?"
A static inner class is probably your best bet. You won't be able to "prevent instantiation of B at all costs" since with reflection, client code can bypass all access modifiers.
You can use anonymous inner class that won't be called B (is anonymous) but will implement A for example
interface A {
void someMethod();
}
public class Test {
static A M() {
return new A() {// it will create and return object of anonymous
// class that implements A
#Override
public void someMethod() {
}
};
}
}
Without using reflection object of anonymous class can be created only by method M. Also it can't be extended so it is good first step to immutability.
You could also use a Proxy implementation to hide the implementation class further
public interface A {
public Object getValue();
}
public class Factory {
public static A newInstance() {
return new ProxyA(AImpl);
}
}
public class ProxyA implements A {
private A proxy;
public ProxyA(A proxy) {
this.proxy = proxy;
}
public Object getValue() {
return proxy.getValue();
}
}
All this is really doing is hiding the implementation of A under another layout and makes it difficult to create a instance of ProxyA
But as #Asaph points out, with reflection, it becomes next to near impossible to truly guard against people accessing various parts of the classes and objects...
You could also separate your interface and implementations via different Classloaders, so that you only ever expose the interface's to the developers and implementations are delivered by dynamic class loading them at runtime. While not solving the underlying problem, it further complicates the matters for those trying to circumvent your factory.
IMHO