Passing the child instance on construction - java

I have a parent class which has methods that need to utilize the child's class instance, but I can't seem to pass it via constructor:
public abstract class CodelanxPlugin<E extends CodelanxPlugin<E>> /* other inheritance */ {
private final E plugin;
public CodelanxPlugin(E plugin) {
this.plugin = plugin;
}
#Override
public void onEnable() {
//need to be able to use the plugin instance
}
}
However, because the child class has to be able to collect a child instance in some form before onEnable is called, I essentially came to this:
public class MyPlugin extends CodelanxPlugin<MyPlugin> {
public MyPlugin() {
super(this);
}
Which is of course not possible since you can't super(this). How can I pass up the child instance upon construction?
One idea I had was:
public MyPlugin() {
super(new Box<MyPlugin>(this).getInst());
}
private class Box<E> {
private E inst;
public Box(E inst) {
this.inst = inst;
}
public E getInst() {
return this.inst;
}
}
However it still calls this before the super() is called, so it's still illegal.
One reason I cannot simple use this in the parent class in the first place is that I pass E as the type argument for some other classes:
protected ListenerManager<E> listener;
#Override
public void onEnable() {
//...
this.getLogger().log(Level.INFO, "Enabling listeners...");
this.listener = new ListenerManager<>(/* need the E instance */);
//...
}
If I pass this to the ListenerManager constructor, I receive this compiler error:
error: incompatible types: cannot infer type arguments for ListenerManager<>
If I use new ListenerManager<E>(this), then my error is:
error: incompatible types: CodelanxPlugin cannot be converted to E

I think you may be confused about how subclassing works. (Either that or I'm completely confused about what you're trying to accomplish.) If you have a class C and a subclass Sub:
class C {
}
class Sub extends C {
}
When the program says new Sub(), it creates one new instance. This object is an instance of Sub, and it is also an instance of C. It doesn't make sense to talk about the methods of C referring to "the child instance".
If you have a Sub object:
Sub myObject = new Sub();
and you call a method that runs code in C:
class C {
public void someMethod() {
// someMethod logic
}
}
myObject.someMethod();
and let's say that method is not overridden. So now you're in the section marked someMethod logic. Within that section, this refers to the object instance you're calling it for (myObject)--which is both an instance of C and an instance of Sub. You do not need a separate syntax to refer to "the child instance", because there's no such separate thing.
So in your original example, if your intent is for the plugin field to be "the child instance of the same object you're just creating", get rid of it. You don't need it.
On the other hand, if you're creating a new object and giving the new object a reference to a different, previously created object, that's a whole other story. But that's not how I understood your question.

You simply don't need to pass "this" to your parent's constructor. 'this' inside MyPlugin's constructor refer to the same object as 'this' inside CodelanxPlugin's constructor.
So what you are writing is simply:
public CodelanxPlugin() {
this.plugin = (E) this;
}
And then, you should wonder wy you'd need a "plugin" field anyway, since "this" will always be available... From your explanation, I feel that you are looking for the template method design pattern.

Related

how does inner class make this reference escape

the noncompliant code example "inner class" section
it seems that there no instance method is called in the inner class, so I don't know how this reference escaped in this snippet.
I've readed some problems, like this, but it is different
public class DefaultExceptionReporter implements ExceptionReporter {
public DefaultExceptionReporter(ExceptionReporter er) {
er.setExceptionReporter(new ExceptionReporter() {
public void report(Throwable t) {
// report exception
}
public void setExceptionReporter(ExceptionReporter er) {
// register ExceptionReporter
}
});
}
// Default implementations of setExceptionReporter() and report()
}
In the constructor of DefaultExceptionReporter, you instantiate an anonymous class. The anonymous class gets a reference to its parent class before the parent class is fully instantiated.
If the parent object had state, it would mean that the anonymous class could theoretically operate on it before it was fully constructed.
Hopefully this demonstrates the potential issue:
class DefaultExceptionReporter implements ExceptionReporter {
private final int foo;
public DefaultExceptionReporter(ExceptionReporter er) {
er.setExceptionReporter(new ExceptionReporter() {
{
System.out.println(DefaultExceptionReporter.this.foo);
}
public void report(Throwable t) {}
public void setExceptionReporter(ExceptionReporter er) {}
});
foo = 1;
}
// ...
}
This will print zero, even though foo is final and assigned 1. A final variable has ended up having two values which should never normally be possible.
Because your object is stateless, I don't think it's a big deal. You should probably declare the class as final though, so it's not possible to extend it and add state.
This happens because when DefaultExceptionReporter publishes the anonymous class, it implicitly publishes the enclosing DefaultExceptionReporter instance as well. You can check this by writing a simple program to actually access that instance:
public static void main(String[] args) {
ExceptionReporter rep = new DefaultExceptionReporter(new ExceptionReporter() {
#Override
public void setExceptionReporter(ExceptionReporter er) {
for (Field field : er.getClass().getDeclaredFields()) {
System.out.println(field);
}
}
#Override
public void report() { }
});
}
Output:
final my.package.DefaultExceptionReporter my.package.DefaultExceptionReporter$1.this$0
This is because an anonymous class is always a non-static inner class (see reference) and these kinds of classes always have an implicit this reference to the enclosing class.
Technically in this example you let this reference escape.
Let's imagine that :
some other thread has access to the ExceptionReporter instance that is passed to the constructor of DefaultExceptionReporter
you actually access the outer instance through DefaultExceptionReporter.this in methods' of your anonymous class instance (for example you want to access field or invoke a method)
In this case other thread might invoke methods on the ExceptionReporter passed to the constructor of DefaultExceptionReporter. And if those methods invoke methods from the instance that is set through setExceptionReporter - other thread can potentially access
DefaultExceptionReporter before it's instance is fully created. The access from other Thread could be done through chain of references :
ExceptionReporter(passed to the constructor) -> ExceptionReporter(anonymous) -> DefaultExceptionReporter.this.

Polymorphism: calling subclass' method from superclass' variable

In Java, when a method is going to be executed, it's declaration is first searched for at the object's real class (that defines the real type of the object). If it's not found, then the superclass is checked. If isn't found there either, the next parent class is checked, and so on. However, look at the example below:
SuperClass s = new SubClass(list of parameter);
s.someMethodExistOnlyInSubClass();
This will give me a compile time error. I thought that, as mentioned above, it would first look for someMethodExistOnlyInSubClass() at SubClass, verify that it exists there and then execute it right away. If I use a variable of the type SuperClass to reference an instance of SubClass some parameters will go to SuperClass's constructor through a call to super() and the object will be instantiated there. In this context, to where have the remaining parameters gone?
By assigning a reference to an instance of SubClass to a variable of the type SuperClass, the variable is treated as if it were referencing an instance of SuperClass. Therefore, it will have no knowledge of any of the methods declared specifically in SubClass. Note, though, that the overrides performed in SubClass will still be effective.
In the context you described, to access someMethodExistOnlyInSubClass() you would have to cast s to the type SubClass. Look below:
((SubClass) s).someMethodExistOnlyInSubClass();
What you are trying to do will work only when the method is defined in both Parent class and subclass.
import java.util.*;
class Parent
{
public void sample()
{
System.out.println("Method of parent is getting Called");
}
}
class Subclass extends Parent
{
public void sample()
{
System.out.println("Method of Child class is getting Called");
}
}
public class Main
{
public static void main(String[] args){
Parent p = new Subclass();
p.sample();
}
}
OUTPUT : Method of Child class is getting Called
If the method exists only in Child class. You will have to create an instance of Child class itself.
Something like this :
import java.util.*;
class Parent
{
}
class Subclass extends Parent
{
public void sample()
{
System.out.println("Method of Child class is getting Called");
}
}
public class Main
{
public static void main(String[] args){
Subclass p = new Subclass();
p.sample();
}
}
Or you can type cast it as mentioned in the earlier post
Parent p = new Subclass();
((Subclass)p).sample();
An object is created based on its declaring class.
When you declare it as SuperClass s the object s wont have any method called someMethodExistOnlyInSubClass . So when you try to invoke this method, even before look at the subclass, you get a compile error.
The object s contrains only everything of the superclass, this object wont be aware of any subclass until u type cast the object to subclass.

How to use methods from extended class on objects from main class? [JAVA]

I'm starting with developing something, and I have few classes that are using the same methods, so I want to have it in one class (to easy fixing in one place etc). Problem is that I dont know how to use methods from different classes on object in main class. Code for explanation:
public class A extends C {
public UiDevice device;
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
public void test(){
methodFromC();
}
}
public class B extends C {
public UiDevice device;
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
public void test(){
methodFromC();
}
}
public class C {
protected void methodFromC(){
device.something();
}
}
I know that I can do it by adding argument to methodFromC:
public class C {
protected void methodFromC(UiDevice device){
device.something();
}
and running it by
methodFromC(device);
But maybe is there better solution?
First of all, as a beginning programmer unless you are doing it for school, avoid extending classes. It ends up a big spaghetti mess until you learn to moderate it (I fell for this one big-time), What you are trying to do isn't good code right now.
I THINK what you are trying to do, however is something like this:
(Assume unspecified code remains pretty much as it is)
class A extends C
{
public UiDevice getDevice()
{
return device;
}
}
abstract class C
{
public abstract UiDevice getDevice();
public methodFromC()
{
getDevice().doSomethingToDevice();
}
}
This pattern allows you to access something from A in a parent class.
B can also have it's own device. I believe this is what you are after (C being able to operate on A's device or B's device depending on which one extended C).
Get rid of the public variable.
You can use the super keyword to access anything from the class you are extending. In your case :
public class B extends C {
public UiDevice device;
device = super.methodFromB();
public void test(){
methodFromB();
}
}
If many of your classes declare methods that do the same thing, you can make them inherit from one class, let's call it class A. In class declare and implement the method. Then in child classes declare methods and in their body write:
super.nameOfYourMethodFromParentClass();
In general, to use a method from different class you just create an object of the class and call a method on it. Like:
class A {
public void myMethod() {
B b = new B();
b.methodFromB();
}
}
When it comes to inheritance be aware of this:
You can create an object of a class that declares this method or of a class that inherits from the class that declares this method and call the method on this object.
Like:
Class A inherits from C. In class C you have method methodFromC() declared. To invoke method from class C on object from class A you can do:
A a = new A();
a.methodFromC(device);
The invoked method here is the method from class C.
But if in class A you override method from class C (that means in class A you declare a method that has the same name and parameters as method in class C), then by executing the code I have written above you will invoke the method from class A, not class C.

Java inheritance: Reducing visibility in a constructor vs inherited method

In the following code, the constructor of Child has reduced visibility from public to private, which is allowed. The inherited methods, such as test(), cannot have reduced visibility. Why does Java operate this way?
class Parent {
public Parent(){}
public void test()
{
System.out.print("parent test executed!");
}
}
class Child extends Parent{
private Child(){}
private void test(){
System.out.print("child test executed!");
}
}
Constructors are not inherited, so Child() doesn't override Parent().
As for the methods, if you have (if Child() were public)
Parent p = new Child();
p.test();
Had it been allowed, this would be invoking a private method. So narrowing the access while overriding is not permitted.
When extending a class you are stating that your class is an extension of the parent class ("IS-A" relationship). What this means is that your class will have all methods of your parent class. This is the same as implementing an interface in java except you gain the method definitions (and fields) from your parent and not just methods declared in the interface. In interfaces constructors are not present because they are not methods. Constructors are special as they belong entirely to the class they are declared on. They declare how to construct only themselves.
In order to construct an object you must know that objects class.
class A {
private message;
private A() {
message = "You created an A";
}
public A(String message) {
this.message = message;
}
public void printMessage() {
System.out.println(message);
}
public static A createAnA() {
return new A();
}
}
class B extends A {
public B() {
super("You created a B");
}
}
A anA = new B(); // This will work
A anotherA = new A(); // This is not allowed as the constructor is private
A yetAnotherA = A.createAnA(); // This works too
So when we constructed B we can say that it is an A. Even though the constructor A is private this is due the constructor not being a part of the interface. The only thing we are saying about B when we assign it to a field of type A is that it has the methods of declared in A. In this case printMessage and createAnA.
That is why you can make the constructor private without changing the definition of the class. Now, why are you not allowed to make the method private when overriding a parents signature. This comes to having varying definitions of the [class].method(). Let's say that you could make your method private. Let's say that you declared a printMssage in the B class. Your reasoning is that you want that method for your use only inside the method and you want your parents printMessage to be used when called externally. Now, you wrote a method like this in the B class.
public void adjustMessage(String additional) {
message = getMessage() + additional();
}
Which version of get message would be executed? Your private one or the public one of your parents? The Java dispatcher would of course choose the public one as it is the one declared in the interface. So we we look at this example we can see if you did make your method have different a lower privilege your method could never be dispatched too which would just make things confusing for the reader.
This is a very good question.

How to call an non overide method of child class using parent object reference

Here is my code want to access child class method of AdapterVer1 getAdaptObj1() (without type casting) using object reference of AdapterVersion (Parent class)
abstract class AdapterVersion {
public abstract void getMObject();
public abstract void getCObject();
}
public class AdapterVer1 extends AdapterVersion {
#Override
public void getMObject() {
System.out.println("AdapterVer1 Mont");
}
#Override
public void getCObject() {
System.out.println("AdapterVer1 Conf");
}
public void getAdaptObj1() {
}
}
public class AdapterFactory {
public static void main(String []a){
AdapterFactory adapterFactory= new AdapterFactory();
AdapterVersion adpater = adapterFactory.getMyObject("ver1");
adpater.getAdaptObj1(); // Unable to do that
((AdapterVer1)adpater).getAdaptObj1(); // Working but DONT WANT THIS
}
public AdapterVersion getMyObject(String version){
if(version.equals("ver1")){
return new AdapterVer1();
}else{
return new AdapterVer2(); // another declared class
}
}
}
You can't do that. Because at compile time, the compiler checks whether the method you invoked is accessible or visible in the class of the reference you are using or not.
So, in this case, since the reference is of Parent class, the compiler will look for the method declaration in the Parent class first in order to successfully compile the code.
Remember: -
Compiler is worried about the Reference type, and at runtime, the actual object type is considered, to decide which method to actually invoke.
The only option you have is to typecast, in which case, the compiler now looks into the class in which you typecasted the reference. Other option is, you can declare an abstract method with that name in Parent class, but from your question, it seems like you explicitly haven't done that.
You would need to move the method declaration to the abstract class.
Rohit already explained it beautifully. Just to add my 2 cents, you should first check the subclass type and then typecast, for instance:
if(adapter instanceof Adapterver1) {
((AdapterVer1)adpater).getAdaptObj1();
}
This way your code will be safer if it tries to handle a new subclass which doesn't declare such method.
But the question you must ask, if you already know what subclass method to call, why accessing it from superclass reference?

Categories

Resources