Remove/Deprecate a method in subclass - java

I want to remove a method from a class that is present in it's super class. I can deprecate the superclass method using the #Deprecated annotation, but it is still accessible in the subclass.
Eg:
public class Sample {
void one() {}
void two() {}
#Deprecated
void three() {}
}
class Sample2 extends Sample {
#Override
void one() {}
public static void main() {
Sample2 obj = new Sample2();
obj.one();
obj.two();
obj.three();// I do not want to access this method through the sample 2 object.
}
}
While using the Sample2 object I only want methods one and two to be available. Please advice on how to do this.
Thanks a lot.

Override three() in Sample2 and throw an exception if that method is accessed.

There is nothing you can do at compile-time. You cannot have a subclass with less methods than a superclass. Best you can do is make a runtime error like #Sudhanshu proposes, and maybe some tooling (like custom FindBugs rules) to flag it an error in your IDE.

Use the private access level modifier in front of methods that should only be accessed in their own classes.
public class Sample {
void one() {}
void two() {}
#Deprecated
private void three() {}
}

One idea for hiding the interface of another class while still using it is to wrap it with your own object (i.e. don't subclass).
class MySample {
private Sample sample;
//maybe other stuff
public MySample(){
sample = new Sample();
}
void one(){
return sample.one();
}
}
This is potentially unsatisfactory: not wanting to use Sample in the entire way it was intended while simultaneously wanting to hijack and extend its behavior. It solves the problem of ever calling three() on your backing Sample.

Related

Check is instance method is called from a constructor

I would like to check, from an instance method of a non-final class, whether the constructors and initializers of that class and its chain of subclasses for the specific instance have already completed.
In the following example, I have a class Abstract, which can be used to implement an interface which allows listeners to be added (which, for simplicity, are just Runnable instances here) and which provides a method signalEvent() which calls all attached listeners.
abstract class Abstract {
protected final void signalEvent() {
// Check that constructs have run and call listeners.
}
public final void addListener(Runnable runnable) {
...
}
}
class Concrete extends Abstract {
Concrete() {
// Should not call signalEvent() here.
}
void somethingHappened() {
// May call signalEvent() here.
}
}
Now it is possible to call signalEvent() from within the subclass constructor, but there is no way that a listener has already been added by that time and the event would just be lost. In our code-base, once in a while, someone adds such a call and I would like to be able to catch such calls as early as possible (using an assert statement or similar).
Is it possible to check whether an instance method is being called, directly or indirectly, from the subclass constructor or initializer of the current instance or, alternatively, is it possible to check whether all constructors for an instance have been completed?
In short, there is no elegant Java mechanism that allows you to do that, but you may consider using a factory pattern. Instead of creating instances directly using new keyword, you could create a factory class, that takes care of creating the actual instance and invokes an additional "post-create" method, that lets the instance know it's been completely created.
If you're using some dependency injection like spring, you get that out of the box, but if not, a solution could look something like this:
interface PostConstruct { // the classes need to implement that
void postConstruct();
}
public class InstanceFactory {
public <T extends PostConstruct> T create(Class<T> clazz, Object... params) {
T instance = //create using reflection
instance.postConstruct();
return instance;
}
}
A solution to the problem to see if a method or code is being called from a constructor. The code below will print true and false respectivly but would be slow and not pretty at all.
I still believe it is not the right solution for the problem above. As Codbender said, better to check if a listener has been added or set a status variable which would be faster
Edit - fixed the issue that Codebender mentioned and also made sure to check back in the stack trace incase of being called a couple of methods deep
public class TestClass extends TestAbstract {
public TestClass() throws Exception {
submethod();
}
public void submethod() throws Exception {
System.out.println(isInConstructor());
}
public static void main(String[] args) throws Exception {
System.out.println(new TestClass().isInConstructor());
}
}
public class TestAbstract {
public boolean isInConstructor() throws Exception {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
for (StackTraceElement element : elements) {
if (element.getMethodName().equals("<init>") &&
TestAbstract.class.isAssignableFrom(Class.forName(element.getClassName()))) {
return true;
}
}
return false;
}
}

Using different method depending on class in Java

I'm trying to reduce some code duplication. Currently i got two methods that are almost identical, the major difference being calling two separate methods within them.
Below is basically what i wanna do:
private void combinedMethod(StandardClass sc, MyClass mc)
{
Method m = null;
if(mc instanceof MySubClass1)
m = sc.RelevantFor1();
if(mc instanceof MySubClass2)
m = sc.RelevantFor2();
m(mc.getA(), mc.getB());
}
I've tested (and it works) this using reflection. But is there a better way of doing it? I read somewhere that reflection is slow and only to be used as a last resort. Is it in this case?
Also in this case the StandardClass is a standard class in the java api. The Class I send in is of my own making.
It isn't clear how exactly those methods look like, or what they are doing, but it seems like a perfect polymorphism case. You can create a method in super class - MyClass I suppose in this case. And override those methods in your subclasses.
Now, when you call that method on MyClass reference, appropriate subclass method will be called based on actual instance. Now invoke whatever method you want to invoke in respective overridden methods.
Somewhere along the lines of:
class MyClass {
public void method(StandardClass sc) { }
}
class MySubClass1 extends MyClass {
public void method(StandardClass sc) {
sc.method(getA(), getB());
}
}
class MySubClass2 extends MyClass {
public void method(StandardClass sc) {
sc.anotherMethod(getA(), getB());
}
}
And then your combinedMethod looks like:
private void combinedMethod(StandardClass sc, MyClass c) {
c.method(sc);
}

Cannot override method and cannot access field while using idiom "Providing a default interface implementation"

Here is code:
IDefaultInterface.aj:
public interface IDefaultInterface {
public void m1();
static aspect Impl{
public int f1;
public void IDefaultInterface.m1(){
}
}
}
DefaulstInterfaceClass.java:
public class DefaultInterfaceClass implements IDefaultInterface {
#Override
public void m1() {
}
void mm() {
f1 = 9;
}
}
In the second piece of code I'm trying to override m1() method and access f1 field. The compiler allows neither one.
How to overcome these limitations?
Additional thoughts. I would not wonder so much if in "AspectJ in action" 2 edition wasn't said about using this idiom that effect should be the same "as extending the default implementation for both (if multiple inheritance was allowed in Java)." I believe that multiple inheritance associated with C++ for majority. So, why not provide the semantics to which people used to?
I'm not fluent in AspectJ, but I see a couple of questionable things: your aspect is trying to define a non-abstract method in an interface, and your class is trying to access field f1 as if it owns the field, when you've declared f1 on the aspect. I'm not quite sure what you're trying to do here, but I don't think you're going about it in the right way.
First of all I misspelled f1 declaration. It should be
public int IDefaultInterface.f1;
It solves access field problem.
The second problem is solved by using following code:
public interface IDefaultInterface {
public void m1();
public static interface Impl extends IDefaultInterface{
static aspect Implementation{
public int IDefaultInterface.Impl.f1;
public void IDefaultInterface.Impl.m1(){
}
}
}
}
And then:
public class DefaultInterfaceClass implements IDefaultInterface.Impl ....

Java Method Overriding - accessing methods in parent - is this possible?

Let's say I create an instance of a class and override one of its methods at the same time - like this
MyClass fred = new MyClass() {
#Override
public void mymethod() {
super.mymethod();
//call something here
}
};
Now let's imagine I want to call a local method which has the SAME name and SAME (lack of) parameters as my overridden method - e.g. I have
public void mymethod() {
//my stuff in here
}
How can I call that from within the overridden method (on the line //call something here)???
Is that even possible? Using
this.mymethod();
causes an endless loop (the overriden method is simply calling itself)
Is there a way of accessing this method (other than via a static reference perhaps?)
Sorry if this is a common question - it's a hard thing to search for and the one question I found had no replies and wasn't really that well-phrased so I'm trying myself!!
I don't have a complier handy so I'm not 100% sure here, but try this:
ParentClass.this.myMethod();
An ugly, but functioning solution:
final MyOtherClass parent = this;
MyClass fred = new MyClass() {
#Override
public void mymethod() {
super.mymethod();
parent.mymethod();
}
};
I'm struggling to see the scenario where you need to do this for naming purposes, but it's useful to know that this in the anonymous class will refer to the anonymous class, not the "parent"; so if you find the need to access the parent's method it's a useful technique.
FWIW, here's a working example.
I am not sure if I fully understood the question but my guess is that you want something like this:
public class ParentClass {
public void mymethod() {
....
}
public void someOtherMethod() {
MyClass fred = new MyClass() {
#Override
public void mymethod() {
super.mymethod();
//call something here
ParentClass.this.mymethod();
}
}
}
}
Note ParentClass.this.mymethod()

Interfaces in Java: cannot make implemented methods protected or private

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

Categories