I am have an interface with an inner class. Now the question is, why cannot I access the functions defined in the outer interface in a similar way to how methods are accessed in outer classes?
I thought things should just work smoothly as this inner class would only be instantiated after a class, implementing the outer interface, being instantiated.
Anyways the error I got was "No enclosing instance of the type OterInterface is accessible in scope"
public interface OterInterface {
public void someFunction1() ;
public void someFunction2() ;
public class Innerclass{
public String value1;
public String value2;
public String getValue1() {
OterInterface.this.someFunction1();
return value1;
}
}
}
Consider what instance of OterInterface you are attempting to perform 'someFunction' on. 'this' refers to the current object - OterInterface is an interface and as such does not have a current object.
So you can't reference OterInterface.this from there, as the compiler has no idea which object instance you are referring to!
In this case you can use anonymous inner class. As you can't instantiate any interface it is impossible to access their methods. Interfaces are incomplete classes with unimplemented methods. In order to instantiate it you have to provide the implementation for its methods.
public interface OterInterface {
public void someFunction1() ;
public void someFunction2() ;
public class Innerclass{
public String value1;
public String value2;
public String getValue1() {
new OterInterface(){
public void someFunction1() {
System.out.println("someFunction1()");
}
public void someFunction2() {
System.out.println("someFunction2()");
}
}.someFunction1();
return value1;
}
}
}
Related
I'm kind of new to java and I'm facing an issue with protected variable in an abstract class. I've added the implementation below:
Abstract class:
public abstract class blah1 implements blah {
protected variable1
//// stuff///
}
sub class:
public class blah2 extends blah1 {
///uses variable1///
}
Checkstyle says I should convert the variable to private and then use get/set methods. But how do I accomplish this within an abstract-class/sub-class situation?
Make variable private in parent class, then add getter and setter
public abstract class blah1 {
private int variable;
public int getVariable() {
return variable;
}
public void setVariable(int variable) {
this.variable = variable;
}
//// stuff///
}
How to use it in the child class. Note the super keyword
public class blah2 extends blah1 {
void useVariable() {
super.getVariable(); // get variable
super.setVariable(1); // set variable
}
}
EDIT
As stated by #Pshemo it's legit removing the super keyword (and you should do it if you're planning to override the getter and setter in order to use the overriden version) obtaining:
void useVariable() {
getVariable(); // get variable
setVariable(1); // set variable
}
Anyway the version using super lets you understand how you can call the original version of those methods
I'm using something similar to the following code in one of my Java classes:
public class SomeClass {
private int someValue;
void incrementValue() {
someValue++;
}
public abstract static class InnerClass {
private final SomeClass toRunOn;
public InnerClass(SomeClass obj) {
toRunOn = obj;
}
public abstract void execute();
// To allow us to call this on a given instance
final SomeClass getObj() {
return toRunOn;
}
}
public final InnerClass called = new InnerClass(this) {
public final void execute() {
incrementValue(); // This is what I thought should be throwing an error
}
};
}
However, while I would expect this to throw a compiler error in the called field defining execute() due to me not giving incrementValue() an object to work on (which is why I allowed for passing this to the inner class), it is completely fine with it. I'm uncertain why this is not giving me an error, and further confused as to what instance it would be calling on.
Am I misunderstanding some form of reference calling here, or is something more subtle going on?
called is assigned an instance of an anonymous sub-class of InnerClass. Since it's an instance member, it is initialized when an instance of SomeClass is created.
Since it is declared in the body of SomeClass, it is an inner class of SomeClass and has access to the instance methods and members of SomeClass. incrementValue() will be executed on the instance of SomeClass for which the called member was initialized.
Perhaps it would be easier to understand if you replace the anonymous class with an equivalent regular inner class :
public class SomeClass {
....
class SubInnerClass extends InnerClass {
public final void execute() {
incrementValue();
}
}
public final InnerClass called = new SubInnerClass(this);
....
}
I am trying to create a generic method, but it requires data from the sub class. Is there a way to do this, or is there a better implementation?
Example of my situation:
public class Super {
public static Object method() {
return doSomethingWith(specificToSubClassValue);
}
}
public class Sub1 extends Super {
public static String specificToSubClassValue = "123";
}
public class Sub2 extends Super {
public static String specificToSubClassValue = "456";
}
I obviously cannot do this. What is a better approach?
One alternative I can think of is to override the #method method in each sub class, but it will be the same code in each instance so I wanted to throw it in the parent class (and it won't be truly overridden since it is static), but I am not sure how to approach it since it is dependent on the sub class value.
Static methods in Java can't be overwritten, and can't access children-specific information: they know nothing about inheritance.
What you need here is instance method, which you can overwrite. An you also may use generics.
public class Super<T> {
public Object method() {
final T specificToSubClassValue = getSpecificToSubClassValue();
if (specificToSubClassValue != null) {
return specificToSubClassValue.hashCode();
} else {
return null;
}
}
protected T getSpecificToSubClassValue() {
return null;
}
}
class Sub1 extends Super<String> {
#Override
protected String getSpecificToSubClassValue() {
return "abc";
}
}
class Sub2 extends Super<Integer> {
#Override
protected Integer getSpecificToSubClassValue() {
return 123;
}
}
Declare an abstract method in Super, which will be used to return the value from the implementing classes. Note that this can only be achieved with non-static methods. As per #JB Nizet's comment, static methods cannot be overriden by subclasses. I've removed the static modifier from the code below to shown you how it would work.
public class Super {
public static Object method() {
return doSomethingWith(specificToSubClassValue);
}
protected abstract Object getValue ();
}
public class Sub1 extends Super {
public static String specificToSubClassValue = "123";
#Override
protected Object getValue () {
return specificToSubClassValue;
}
}
public class Sub2 extends Super {
public static String specificToSubClassValue = "456";
#Override
protected Object getValue () {
return specificToSubClassValue;
}
}
Well, te whole idea of inheritance is that the superclass should not be able to do that much without the sub-class. Otherwise the whole inheritance would be pointless exercise and spaghetti code. But you are tackling the problem the wrong way. Make sub-class "spill" the data you need (through getter) and use the generic method from superclass on the data in the sub-class.
Also the overriding of super class methods is highly overrated. You should strive for your super method to be as flexible and re-usable as possible, and even then strive rather for overloading, instead of overriding.
You could have:
public class Super {
public Object method(String specificValue) {
return doSomethingWith(specificToSubClassValue);
}
And then have your sub do this
public class Sub1 extends Super {
public static String specificToSubClassValue = "123";
Object method(specificToSubClassValue);
}
This way you accomplish exactly what you want, operate on the class specific value using the super method.
I just answered this question by saying how to solve the compilation problem:
How to use fields in java enum by overriding the method?
But what I don't understand is why the error is happening in the first place.
Here is the example written as an enum:
public enum MyEnum {
FIRST {
#Override
public String doIt() {
return "1: " + someField; //error
}
},
SECOND {
#Override
public String doIt() {
return "2: " + super.someField; //no error
}
};
private String someField;
public abstract String doIt();
}
Here is the exact same thing as abstract classes
abstract class MyClass {
class FIRST extends MyClass {
#Override
public String doIt() {
return "1: " + someField; //no error
}
};
class SECOND extends MyClass {
#Override
public String doIt() {
return "2: " + super.someField; //no error
}
};
private String someField;
public abstract String doIt();
}
In the case of FIRST within the enum implementation it cannot access someField. However in the abstract class case it can.
Additionally adding super fixes the problem, as does removing the private modifier on the field.
Does anyone know why this slight quirk in the behaviour is happening?
Your abstract class is not equivalent to your enum, since enums are implicitly public static final. Thus, you'll observe the same behavior if you use:
abstract class MyClass {
static class FIRST extends MyClass {
#Override
public String doIt() {
return "1: " + someField; // error
}
};
static class SECOND extends MyClass {
#Override
public String doIt() {
return "2: " + super.someField; // no error
}
};
private String someField;
public abstract String doIt();
}
As explained in http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html, chapter "Static Nested Classes":
A static nested class cannot refer directly to instance variables or
methods defined in its enclosing class: it can use them only through
an object reference.
Thus the need of super. You could also use this if the field were protected rather than private.
When an identifier is resolved, Java prefers the lexical scope over inherited members. So when you have an inner class that extends the outer class and use a field of the outer class without using this or super, the field of the outer instance is accessed which fails if the inner class is static as there is no outer instance then. In contrast, when using super you are explicitly accessing the inherited member. Note that enum classes are implicitly static. You can even use this to access the inherited member but you have to use ((MyClass)this).someField to access it if it’s declared private.
Class FIRST is an inner class of MyClass and also a sub class. The reason you do not see an error when accessing someField in it is because you are accessing the someField of the outer class, not the super class.
class MyClass {
class FIRST extends MyClass {
#Override
public String doIt() {
super.someField = "super";
return "1: " + someField;
}
};
private String someField = "outer";
public String doIt(){return "";}
public static void main(String[] args) {
System.out.println(new MyClass().new FIRST().doIt());
}
}
Prints 1: outer.
In the other case your enum constants behave as static nested sub classes, not inner classes, so they do not have a reference to the outer class, only their super class.
I disagree with the accepted answer.
The enum const declaration is implicit public static final, but not the class the enum const belongs to.
From JSL Chapter 8.Classes
The optional class body of an enum constant implicitly defines an anonymous class declaration (§15.9.5) that extends the immediately enclosing enum type. The class body is governed by the usual rules of anonymous classes.
And what the 'rules of anonmous classes'?
From JSL Chapter 15:
An anonymous class declaration is automatically derived from a class instance creation expression by the Java compiler.
An anonymous class is never abstract (§8.1.1.1).
An anonymous class is always implicitly final (§8.1.1.2).
An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1).
And if the enum equivalent class is a static class, how to explain the following error?
public enum MyClass {
First {
public static int b; //(2)Illegal static declaration in inner class
};
}
But why a inner class can't access the outer class's field?
A possible enum equivalent class may looks like following, which gives the same error as a enum class:
abstract class MyClass {
private int someField;
static {
class First extends MyClass {
public void method() {
System.out.println(someField);
}
private static int b;
}
}
}
More:
Nested enum is static?
How is enum implemented?
I have a base class and subclass. Base class has common methods and its implementation which I want to use in subclass but I want to use subclass member variable instead of superclass. I do not want to rewrite the same method in subclass. Is there a way in Java to achieve this.
You could create a protected setter on the member variable & then override the value of the super's variable within the constructor of the subclass:
class Animal {
private String voice = "Oooo";
protected void setVoice(String voice) {
this.voice = voice;
}
public void speak() {
System.out.println(this.voice);
}
}
class Dog extends Animal {
public Dog() {
setVoice("woof");
}
}
You can use a method to access the member and override it in subclasses.
Class A{
public void DoStuff(){
int aux = getResource;
/*cool things with aux*/
}
protected int getResource(){
return internal_member;
}
private int internal_member;
}
Class B extends A{
private int another_member;
#Override
public int getResource(){
return another_member;
}
}
But take into account that this will not prevent people chaging class A from using the member directly, It might be better to create a base class for the members and the getters.
Another Option, as some people outlined before is to have the data member in the base class as protected and initialize it in the subclass:
Class A{
public void DoStuff(){
/*cool things with internal_member*/
}
protected List internal_member;
A(){internal_member = /*Set here a value*/}
}
Class B extends A{
B(){internal_member = /*Set a different value here! you can even declare a member and assign it here*/}
}
You can use constructors with arguments if you need.