Ambiguity for Variable but not for Method - java

We have an interface and class with no relation each having methods with same signature. These can be related to a class which would compile fine.
interface A {
void test();
}
class B {
public void test() {
System.out.println("Test");
}
}
public class MultipleLevelInheritance extends B implements A {
public static void main(String[] args) {
new MultipleLevelInheritance().test();
}
}
But when we do the same with the a variable its causing ambiguity.
interface A {
int a = 10;
}
class B {
public static int a = 9;
}
public class MultipleLevelInheritance extends B implements A {
public static void main(String[] args) {
System.out.println(a); //The field a is ambiguous
}
}
Even if we keep a as final in B, its still causing the error. Why is that valid for methods and invalid for variables?

When you implement an interface, all variables are inherited in the class. So, when you extend a class and implements the interface, it will have two declaration of variable a. Hence you are getting ambiguity error.
But when it comes to methods, when you implement the interface, you are expected to provide the implementation of the methods defined in interface. In your example, this implementation is provided by class B. Therefore there is no error.

Your class MultipleLevelInheritance is implementing an interface and extending a class, and both have the same property name (a),when you call a in MultipleLevelInheritance, Java is not able to determine if the variable refers to A.a or B.a. you just need to prefix it.

Related

Cannot define extra methods in an Anonymous Inner Class in Java

When defining extra methods (that do not override the super class methods) in an Anonymous Inner Class the code compiles fine without any issues but if I try to call the extra method it throws an error. So is it only possible to override methods in the sub class when extending with an anonymous inner class? If it is so can anyone please explain me why?
Here's what my code looks like
class SomeClass {
public static void main(String[] args) {
SomeOtherClass a = new SomeOtherClass() {
#Override
public void methodFromSuperClass() {
System.out.println("Method from super class!");
}
public void subClassMethod() {
System.out.println("Sub class method");
}
};
a.methodFromSuperClass(); //This works fine
a.subClassMethod(); // But calling this extra method throws an error
}
}
This is the error that I'm getting
SomeClass.java:20: error: cannot find symbol
a.subClassMethod();
^
symbol: method subClassMethod()
location: variable a of type SomeOtherClass
1 error
This situation is exactly the same as if the anonymous class had a name:
class SomeOtherClass {
public void methodFromSuperClass() { }
}
class Subclass extends SomeOtherClass {
#Override
public void methodFromSuperClass() {
System.out.println("Method from super class!");
}
public void subClassMethod() {
System.out.println("Sub class method");
}
}
And you did:
SomeOtherClass a = new Subclass();
a.subClassMethod();
Wouldn't you agree that you shouldn't be able to call subClassMethod here? After all, the compiler knows that a is of type SomeOtherClass, but not which subclass of SomeOtherClass it is. It doesn't analyse your code that far back to see that you actually assigned an instance of Subclass to it.
The situation with anonymous classes is basically the same. It's just that this time, the subclass doesn't have a name in your code, but it's still a subclass, and the same reasoning that "the compiler doesn't analyse your code that far back" applies.
Since the anonymous subclass has no name, you can't do something like Subclass a = new Subclass(); as in the named subclass example, but since Java 10, you can do:
var a = new SomeOtherClass() { ... };
var lets the compiler infer the type of the variable for you without you saying the type name. The compiler will infer the anonymous subclass as the type for a, and this will allow you to do:
a.subClassMethod();
Finally, it is totally allowed to declare extra members in anonymous classes - it's just rather hard to access them from anywhere other than inside the anonymous class, or the local scope, because the anonymous class has no name. Declaring extra members is still sometimes useful though, because you can access them in the overridden methods for example.
Your assumption is correct. It is not possible to call the unoverridden method this way.
Consider an example where you have declared an interface and instantiated it with a concrete class, then you still only have access to the methods defined in the interface and not in the class.
public interface MyInterface{
public void someMethod();
}
public class MyImpl implements MyInterface{
//someMethod() implementation
// ...
// newMethod()
public void newMethod(){
//some implementation
}
}
public class Main{
public static void main(String[] args){
MyInterface inter = new MyImpl();
inter.someMethod(); // this call is ok
inter.newMethod(); // this call leads to a Symbol not found Exception,
// because MyInterface has no method named newMethod...
}
}
Hope it is now clearer what is meant by this

How can I make classes implement an interface and print their methods based on a given parameter in Java?

I think this might be a very basic Java question, and I apologize since I'm a beginner, but I want to understand what am I getting wrong here: I'm supposed to create a package, and inside it, I must create the following:
an interface with a method (the question says nothing besides it, so I created it empty)
2 classes, A and B, which must implement the method created in said interface and print their own names
A third class, C, which must override B's implementation
And an Execute method inside the main class. This method must receive a letter as a parameter, no matter if it's capital case or not, and execute the method of the corresponding class (i.e. if this method receives as a parameter the letter A, it must execute the method belonging to class A)
So far I came up this this, but the code receives the input, and doesn't do anything:
Interface
public interface Test {
public static void testInterface() {
}
}
Classes
public class Teste {
public static void main(String[] args) {
class A implements Test {
public void testInterface() {
System.out.println("A");
}
}
class B implements Test {
public void testInterface() {
System.out.println("B");
}
}
class C extends B {
public void testInterface() {
System.out.println("C");
}
}
Scanner inputLetter = new Scanner(System.in); // Create a Scanner object
System.out.println("Enter a letter from A to C: ");
String resLetter = inputLetter.nextLine(); // Read user input
if (resLetter == "A") {
A a = new A();
a.testInterface();
}
if (resLetra == "B") {
B b = new B();
b.testInterface();
}
if (resLetra == "C") {
C c = new C();
c.testInterface();
}
}
}
To be quite honest, I may be messing up with the code's structure too, since I'm not too sure of how should I organize it - I didn't create the Execute method because I had a lot of trouble creating classes without the main method, and couldn't put a method inside another, and I want to make it as simple as possible to make it work before I can try bolder things, so any help will be of great value!
You're on a good way. I'll just post some information to get you over your current roadblock.
public interface MyTestInterface {
void testInterface();
}
Interfaces will just "announce" a method. This just tells you (and the compiler) that any Class that implements MyTestInterface has to supply a method called testInterface(). Don't make them static, as this would prevent any class implementing the interface from overriding the method.
Put your classes in their own .java file. While you can define a class within a class (so called Inner Class), it has some implications.
A.java
public class A implements MyTestInterface {
#Override
public void testInterface() {
// Objects of Class A do something here
}
}
MyMain.java
public class MyMain {
public static void main(String[] args) {
MyTestInterface implementedByA = new A();
implementedByA.testInterface();
}
}
Since it implements MyTestInterface, an Object of Class A is both an instance of A and an instance of MyTestInterface. This allows you, to declare a variable of type MyTestInterface and assign it an implementation of one implementing class.
And as #Amongalen mentioned: How do I compare strings in Java?

Calling a method of abstract class from a concrete class without extending

Example abstract class is bellow.
public abstract class Vehicle {
void maintain(String str) {
System.out.println(str);
}
}
Example concrete class is bellow.
public class Driver {
public static void main(String[] args) {
}
}
Now I need to access the maintain method without extending the Vehicle class.Is there any way to do this without using static content?
No, there isn't, because maintain is an instance method. To call an instance method, you must have an instance. You can't create an instance of an abstract class.
You can subclass it anonymously (see this tutorial), but you still need to subclass it.
You can use an anonymous inner class. I've used your example code but also defined an anstract method in Vehicle
public class AbstractTest {
public static void main(String[] args){
Vehicle v = new Vehicle() {
#Override
void myOtherAbstractMethod() {
// Do what you need here
}
};
v.maintain("foo");
}
public static abstract class Vehicle {
void maintain(String str) {
System.out.println(str);
}
abstract void myOtherAbstractMethod();
}
}
You cannot do that as abstract classes are abstract. Also in your case there's no connection between Driver and Vehicle so even if you would be able to compile that code (you won't), then ClassCastException would show up.
You must extend abstract class first, like it or not.

Why the answer will be "GOOD"?

Following is the code I tried to run, the output was Good. So, we can use a variable of interface implemented by a class?
interface IDummyInterface {
public String TYPE = "Good";
}
class Test implements IDummyInterface {
}
public class MyApplication {
public static void main(String[] args) {
System.out.println(Test.TYPE);
}
}
Any class that implements an interface, and any class that extends a class that implements that interface, inherits all of that interfaces variables. No matter how you declare the variables in the interface, all interface variables are public static final, which is why you can access them with just the class name and not an instance of the class.
Test implements IDummyInterface.so all variables of IDummyInterface are inherited
The variable is actually static final. And since it is static, it follows the same rules as all static variables declared in classes, which are accessible through any other class that inherit from it. In that regard interfaces behave like classes.
class StaticTestParent { public static final int VALUE = 1; }
class StaticTestChild extends StaticTestParent { }
static {
System.out.println(StaticTestChild.VALUE);
}

Inner classes inside Interface

Can we have a class inside an interface which has different methods of the interface implemented in it. I have a doubt here that why Java allows writing Inner classes inside interfaces and where can we use it.
In the program below I have written a class inside Interface and implemented the methods of the interface. In the implementation class of the interface I have just called the inner class methods.
public interface StrangeInterface
{
int a=10;int b=5;
void add();
void sub();
class Inner
{
void add()
{
int c=a+b;
System.out.println("After Addition:"+c);
}
void sub()
{
int c=a-b;
System.out.println("After Subtraction:"+c);
}
}
}
abstract public class StrangeInterfaceImpl implements I {
public static void main(String args[])
{
StrangInterface.Inner i=new StrangeInterface.Inner();
i.add();
i.sub();
}
}
You can define a class inside an interface. Inside the interface, the inner class is implicitly public static.
From JLS Section 9.1.4:
The body of an interface may declare members of the interface, that is, fields (§9.3), methods (§9.4), classes (§9.5), and interfaces (§9.5).
From JLS Section 9.5:
Interfaces may contain member type declarations (§8.5).
A member type declaration in an interface is implicitly static and public. It is permitted to redundantly specify either or both of these modifiers.
The only restriction on the inner class defined inside the interface or any other class, for that matter, is that, you have to access them using the enclosing member name.
Apart from that, there is no relation between them. The inner class will result in completely a different class file after compilation.
For e.g., if you compile the following source file:
interface Hello {
class HelloInner {
}
}
Two class files will be generated:
Hello.class
Hello$HelloInner.class
Can we have a class inside an interface which has different methods of the interface implemented in it.
IMHO But interfaces are not meant to for that purpose.
If you write inner class in an interface it is always public and static.
It's equivalent to
public interface StrangeInterface
{
public static class Inner{
}
and the variable inside the interface also explicitly public static variables.
An interface might provide its own implementation as a default.
Note that unless you declare the inner class implements the interface, there's no relation between the two other than it's an inner class. When a class is very tightly related to the interface this isn't intrinsically unreasonable, although I'd be suspicious it's a generally-useful pattern.
to summarize "where can we use it" by defining a class inside an interface:
1. to provide default implementation for an interface
2. if argument or return type for interface method/s is class
w.r.t your code
interface StrangeInterface {
int a = 10;
int b = 5;
void add();
void sub();
class Inner implements StrangeInterface {
public void add() {
int c = a + b;
System.out.println("After Addition:" + c);
}
public void sub() {
int c = a - b;
System.out.println("After Subtraction:" + c);
}
}
}
class MyTest implements StrangeInterface {
public void add() {
System.out.println("My own implementation for add : " + (a +b));
}
public void sub() {
System.out.println("My own implementation for sub : " + (a- b));
}
}
public class StrangeInterfaceImpl {
public static void main(String args[]) {
StrangeInterface.Inner i = new StrangeInterface.Inner(); // calling default implementation
i.add();
i.sub();
MyTest t = new MyTest(); // my own implementation
t.add();
t.sub();
}
}

Categories

Resources