Instantiate an inner class inherited with protected access specifier - java

I wanted to make the following exercise from Bruce Eckel's TIJ on inner classes:
Create an interface with at least one method, in its own package.
Create a class in a separate package. Add a protected inner class
that implements the interface. In a third package, inherit from
your class and, inside a method, return an object of the protected
inner class, upcasting to the interface during the return.
Here's my implementation:
first, the interface:
package workers;
public interface Employable {
void work();
}
then, a class with an inner class implementing the interface:
package second;
import workers.Employable;
public class WorkersClass {
protected class Worker implements Employable {
#Override
public void work() {
System.out.println("Hello, I'm a worker!");
}
}
}
and finally the inherited class:
package third;
import second.WorkersClass;
import workers.Employable;
public class Third extends WorkersClass {
Employable getWorker() {
return new Worker();//the line is reported to be incorrect
}
}
IDEA underlines the line with Worker() in getWorker and suggests to make the Worker class public. But why? It's protected that's why successors of WorkersClass can instantiate the Worker class in their methods. Do I misunderstand something?

The problem is not all with access specifier.
When you don't provide any constructor in a class, the compiler automatically inserts a default, no-args constructor for you
That's not true here in this case. Because the compiled inner class doesn't get the default constructor since it gets compiled as outer$inner and for that inner there is no default constructor provided by compiler.
Provide a default no org constructor manually and see the magic :)
package second;
import workers.Employable;
public class WorkersClass {
protected class Worker implements Employable {
public Worker() {
// TODO Auto-generated constructor stub
}
#Override
public void work() {
System.out.println("Hello, I'm a worker!");
}
}
}

modify WorkersClass
public class WorkersClass {
protected class Worker implements Employable {
public Worker(){}
#Override
public void work() {
System.out.println("Hello, I'm a worker!");
}
}
}

Your Third class inherits WorkersClass and not Worker.
Java does not really consider inner classes, it is a simple hack introduced in Java 1.1. The compiler generates class Worker "outside" of class WorkersClass, but in the same package.
That's why, in order to implement a new Worker instance from a Third method, you need to add a public constructor to Worker:
protected class Worker implements Employable {
public Worker(){
}
#Override
public void work() {
System.out.println("Hello, I'm a worker!");
}
}

Related

Abstract callback in reflection method of java

I have a class in jar of which I want to invoke a method. But that method has parameter of abstract class and that abstract class is inner method of class in jar. AbstractClassA is a HIDDEN class. Here is code:
public class A{
private invokeThisMethod(AbstractClassA object){
}
public abstract class AbstractClassA {
public void update(int remaining){}
}
}
public class myClass{
//using Reflection get object of class A
objectOfClassAusingReflection.inovke("invokeThisMethod", params)
}
Problem here is how do I create concrete implementation of AbstractClassA to pass in invoke method and get update method callbacks ?
Something like this should work:
AbstractClassA a = new AbstractClassA() {
public void update(int remaining) {... do something...}
};
objectOfClassAusingReflection.inovke("invokeThisMethod", a);
You cannot create an instance of abstract class or any interface at runtime.
Instead create an anonymous class for this.
public abstract class A {
public void fun(){....}
public abstract void absFun();
}
public class MyClass {
objectOfClassA = new A(){
public void absFun(){...}
}
}
Or you can first create implementation for that abstract classes for which you will have to create another class extending A
class AWrapper extends A {
public class ImplementationClassA extends AbstractClassA {
// override abstract functions...
}
}
Now you can use this Awrapper class
AWrapper wrapperObj = new AWrapper();
A obj = wrapperObj; // just to make it clear that A can hold wrapperObj as it is implementation of it.
A.AbstractClassA absObj = wrapperObj.new ImplementationClassA();
...
objectOfClassAusingReflection.inovke("invokeThisMethod", params)
Below code should work--
Here, i used anonymus classes for both outer and inner class and then with the help of getdeclatedMethod called your update method.
"TestAbs" is your jar class--
public abstract class TestAbs {
private void invokeThisMethod(AbstractClassA object) {
}
public abstract class AbstractClassA {
public void update(int remaining) {
}
}
}
Then calling your jar class from "TestAbs1" like below--
public class TestAbs1 {
public static void main(String[] args) {
TestAbs.AbstractClassA abs = new TestAbs() {
AbstractClassA a = new AbstractClassA() {
public void update(int remaining) {
System.out.println("Inside update method : " + remaining);
}
};
}.a;
try {
int i = 1;
Class<?> class1 = Class.forName("app.test.mytest.TestAbs$AbstractClassA"); -- (*Getting instance of inner class*)
System.out.println(class1.getDeclaredMethod("update", int.class));
class1.getDeclaredMethod("update", int.class).invoke(abs, i);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
The output i got is --
public void app.test.mytest.TestAbs$AbstractClassA.update(int)
Inside update method : 1
Answer to your Comment:-
What I understood from your comment is that, you wanted to call method from abstractClass which is hidden in outerclass.
As per my understanding, there is one way like below--
public abstract class TestAbs {
private void invokeThisMethod(AbstractClassA object) {
}
private abstract class AbstractClassA { --- your hidden class
public void update(int remaining) {
}
}
public class ImplementedClass extends AbstractClassA{ -- use implemented class here
....
...
}
}
And after that, use your ImplementedClass the same way mentioned above.
You can find reference example for private inner class here from java docs.
Note: In your question context, since your inner class and outer class is in jar, so I think it is difficult for you add implementation class in your jar.
In case, you find any alternatives, please let all knows about this;
thanks.

Could we call super.someMethod() in derived class from an abstract class?

Could we call super.someMethod() in derived class from an abstract class?
for in stance:
abstarct class TestBase{
void nonabstractMethod(){
....
}
}
Then derived class:
class Child extend TestBase{
void callFunction(){
}
void nonabstractMethos(){
super.nonabstractMethos();
}
}
I assume this can be done. But if we have an abstract method then it cannot be called because of no implementation, am i correct?
The short answer: yes.
You can always call a public or protected super method. Like any (instance) method in java, it will be handled polimorphicly, and a concrete implementation will be called, either of the super's class or from the derived class if it overrides it.
Yes you are correct. If you are extending an abstract class having abstract method, you can't call super.thatMethod();
Consider the following example
public class RSAService {
protected void doRSA(){}
}
class MyService extends RSAService{
public void myService(){
super.doRSA(); //Works fine
}
}
This will work as the doRSA() is accessible from the MyService. Same for public but not for private
But
public abstract class RSAService {
protected abstract void doRSA();
}
class MyServe extends RSAService{
public void myService(){
super.doRSA(); //This won't work
}
#Override
protected void doRSA() {
}
}
Now consider this case, where you can call the super.superClassMethod() from your subclass
public abstract class RSAService {
protected void doRSA(){}
}
class MyService extends RSAService{
public void myService(){
}
#Override
protected void doRSA() {
super.doRSA();
}
}
So if you are overriding a super class method you can call the method using super. Consider this Java Specification link for more clarification
Your example will work if both classes are in the same package.
If that is not the case, then you should declare the method protected or public, something like:
abstract class TestBase{
protected void nonabstractMethod(){
....
}
}
If your method is abstract, then you can't call it, for example:
abstract protected void abstractMethod();

implement an abstract method in derived class as static

I have these 2 classes
class A {
public void foo1() {
...;
foo2();
...;
}
protected abstract foo2();
}
class B extends A {
public foo2() {
......
}
I need foo2 to be static so I can do B.foo2() but I also want the functionality in class A to remain.n
Any suggestions?
}
You can't override static methods or implement abstract methods as static.
Static methods are defined on a class definition, not on a class instance. Abstract methods are defined on a class instance.
What you said doesn't make sense in fact.
Although I don't quite get why you need to do it, there is a workaround:
class B {
#Override
public void foo() {
fooUtil();
}
public static void fooUtil() {
// your impl here
}
}
Then you can do B.fooUtil() instead, and using its behavior to override A.foo().

Can't cope with inheritance

I have (some pseudocode):
public class Thrd extends Thread{
protected void letUsFinalize(){
int a = 0; // Just for debugging.
}
}
public class FreeThread extends Thrd{
#Override
protected void letUsFinalize() {
FreeThread.this.interrupt();
}
}
Please, have a look at the picture. Our object now is of class FreeThread (visible in the Variables subsection). So, I come to the upper break point in the picture, press Step into and I occur at the lower break point. I mean that I occur in the method of the class Thrd (superclass).
What should I do so that the method of subclass would execute in this case?
If the object that you are using is an instance of FreeThread, then calling object.letUsFinalise() will call the method from FreeThread.
It looks like you are calling letUsFinalise() from the super class, so it's not possible to call the subclass' method unless you are using a static object to it (demonstrated below).
public class SuperClass {
public void method(){
Objects.object.method();
}
}
class SubClass extends SuperClass{
#Override
public void method(){
System.out.println("I'm the sub class!");
}
}
class Objects{
public static SubClass object = new SubClass();
}
I suggest that you create a static object of FreeThread and use that to call the method, as shown above.

Java call function when created in superclass

I'm trying to create a game engine in Java that uses the syntax and structure of UnityScript, and i've got most of it figured out at the moment. The only thing i'm struggling with is being able to call functions when instantiating a class from the superclass.
Example:
Object superclass:
public class Object {
public Object(){
Start();
}
public void Start(){
}
}
Gameobject subclass:
public class GameObject extends Object {
public GameObject(){
}
public void Start(){
}
}
The thing i want to happen is that when i create a new gameobject or anything that extends from a gameobject calls the Start() function when instanced, preferably without using the super() statement.
Parent no-argument constructors will be called automatically if you exclude the super statement, so your code will work as-is.
Fix your method names to follow convention.
Have your super class implement a private method that does its general logic and then calls the start() method, possibly your sub class'. Put a call to this private method in the constructor of the super class.
Your superclass
public abstract class SomeObject {
public Object(){
objectStart();
}
private void objectStart(){
// do something general
start();
}
public abstract void start();
}
Gameobject subclass:
public class GameObject extends SomeObject {
public GameObject(){
// implicitly calls super() which will call objectStart() which will call start()
}
#Override
public void start(){
}
}
Now when any subclass of SomeObject gets instantiated, its start() method will get executed.
If you don't want the class to be abstract, just implement a no-op start() method

Categories