I have declared the following interface in Java:
public interface ITest {
void doStuff();
}
which is implemented by another few classes who overwrite the doStuff() method. I then use this interface as the type in a function:
public gonnaDoSomeStuff(ITest fun) {
fun.doStuff();
}
However, Java (and Eclipse) state that the method is undefined for type ITest. What am I doing wrong?
It turns out that the class containing my gonnaDoSomeStuff method was appended with a generic, which was being referenced instead of the actual interface.
Wrong
public class Dog<ITest> {
public gonnaDoSomeStuff(ITest fun) {
// ...
}
}
Right
public class Dog {
public gonnaDoSomeStuff(ITest fun) {
// ...
}
}
You can not access default declared method in a public class because its scope is limited. You should declared it as public for call in public class.
Related
In my project I have a superclass and two subclasses extending from it. There is a method in the superclass that is overriden differently in each subclass.
I want to know if it's possible to introduce a method (in another class) that takes object of either subclass as a parameter and calls a method overriden in one of subclasses (depending on to which subclass does the object belong).
public class Superclass{
public int method(){return 0;}
}
public class Subclass1 extends Superclass{
public int method(){return 1;}
}
public class Subclass2 extends Superclass{
public int method(){return 2;}
}
public class CallingClass{
public static int dependantCall(Superclass parameter){return parameter.method}
I want to be able to do something like
Subclass1 subclassObject = new Subclass1;
System.out.println(CallingClass.dependantCall(subclassObject));
and get output
1
That is what Polymorphism is for! Defining the Superclass as a parameter type will allow you to pass either subclass in.
For example in your other class you can define it like this:
// classes Dog and Cat extend Animal and override makeNoise()
class Owner{
playWith(Animal a){
a.makeNoise();
}
}
Now the Owner can accept owner.makeNoise(cat) and owner.makeNoise(dog)
More reading: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
Yes, it is entirely possible. Here's how that method would look like:
public <T extends Superclass> void foo(T subclassObject) {
...
}
Or:
public void foo(Superclass obj) {
...
}
Note that in the above method, you can pass subclasses' objects as well (they are covariant data types).
This is what Java does by default when you create subclases, so no need to do anything special. Each object carries it's type information at run time, and the method invoked would always be the most specific one for the object. Example:
public class Doer {
public void doSomething() {
// Body presence
};
}
public class Painter extends Doer {
#Override
public void doSomething() {
// Paint here
}
}
public class Manager extends Doer {
#Override
public void doSomething() {
// Micromanage here
}
}
// Elsewhere in your code:
public void busyness(Doer doer) {
doer.doSomething();
}
A style note: if it is possible, one should prefer using interfaces instead of base classes (base classes those should be used only if you want to share implementation between subclasses). Example with interfaces:
public interface Doer {
void doSomething();
}
public class JackOfAllTrades implements Does {
#Override
public void doSomething() {
// Do whatever necessary
}
}
// Client code stays exactly the same as above:
public void busyness(Doer doer) {
doer.doSomething();
}
Note that in Java a class can have only one base class but can implement multiple interfaces.
#Override annotations are not strictly required, but they help Java compiler to spot some errors for you (e.g. if you misprint method name).
In your example it would look like
public class CallingClass {
public static int dependantCall(Superclass parameter) {
return parameter.method();
}
}
Subclass1 subclassObject = new Subclass1();
System.out.println(CallingClass.dependantCall(subclassObject));
Consider the following scenario:
Say that you created an interface Foo:
public interface Foo {
public void bar();
}
And say that there is an old class SomeOldClass in a certain library that you want to use. It already has the bar() method, but does not explicitly implement Foo.
You have written the following code for all classed that implement Foo:
public <T extends Foo> T callBarOnThird(List<T> fooList){
return fooList.get(2).bar();
}
And now you want it to also work for SomeOldClass. You dont have access to the source code of this class, so you can't modify it.
Is there a way to declare Foo or something similar as some sort of "soft" interface, (as in where any class that implements all the required methods would be accepted as an implicit implementation of the soft interface)? If not, how would you solve this with code that is as clean as possible?
No, it does not.
You have to provide an adapter instance (there are several methods and tools to help with that, but Java does not do it "implicitly").
Java is statically typed and dynamically bind.
Dynamically bind: This means that the linking between a method signature and its implementation happens at runtime. For example.
For example
public interface MyInterface {
void doStuff();
}
public class MyFirstImpl implements MyInterface {
#Override
public void doStuff() {
// do some stuff here
}
}
public class MySecondImpl implements MyInterface {
#Override
public void doStuff() {
// do some stuff here
}
}
So if you would have the next snippet
MyInterface test; // pointing to either MyFirstImpl or MySecondImpl
test.doStuff();
The JVM will determine at runtime weather to call the doStuff method from MyFirstImpl or MySecondImpl based on the runtime type of the object.
Statically typed: This means that the JVM will check at compile time weather a there is a method to call regardless of the implementation.
For example:
public interface MyInterface {
void doStuff();
}
public class MyFirstImpl implements MyInterface {
// no override here
public void doStuff() {
// do some stuff here
}
}
public class MySecondImpl implements MyInterface {
// no override here
public void doStuff() {
// do some stuff here
}
}
So if you would have the next snippet
MyInterface test; // pointing to either MyFirstImpl or MySecondImpl
test.doStuff();
The compiler will complain because it can't ensure at compile time that regardless of the implementation of MyInterface there is a doStuff method to call (although in this case, both implementations of MyInterface define a doStuff method).
This ensures that you won't get a NoSuchMethodException at runtime, if you would pass, for example, the next implementation.
public class MySecondImpl implements MyInterface {
// no override here
// no doStuff method
}
This adds some type safety to the language at the cost of some rigidity (since you are able to determine the issue earlier than at runtime and therefore you have a shorter feedback loop, at the cost of the scenario in which all the implementations actually expose the method not working out of the box).
How you should refactor your code:
Create a wrapper over the third party library and expose the interface from the wrapper.
public interface Foo {
void bar();
}
public class ThirdPartyFooWrapper implements Foo {
private SomeOldClass oldClass;
public ThordPartyFooWrapper (SomeOldClass oldClass){
this.oldClass = oldClass;
}
#Override
public void bar() {
this.oldClass.bar();
}
}
Then, in your code use ThirdPartyFooWrapper instead of SomeOldClass.
Hope this answers your question!
Extension to Thilos answer.
You can also use the decorator to handle this
public <T extends Foo> T callBarOnThird(List<T> fooList){
return new BarDecorator(fooList.get(2)).bar();
}
Inside the decorator, you can check if given Object is the instance of Foo or not then do operations accordingly.
but I've been programming in Java so I know you can Override methods in Object's instantiation
private MyObject myObject=new MyObject(){
#Override
public void myMethod(int args){
.
.
.
}
}
can somebody show me how to do this in C# please.. Thanks
Unlike Java where all instance methods a virtual ones, in C# you have to put virtual keyword explicitly:
public class MyObject {
...
// in order to be overriden in a derived class, base method should be
// explictly declared as virtual or abstract
public virtual void myMethod(int args){
...
}
...
}
In C# override is a keyword as well, not just an attribute:
// class can't be declared locally, but explictly
public class MyOverridenObject: MyObject {
...
// override is a mandatory keyword in the context
public override void myMethod(int args){
...
}
}
Finally, C# doesn't allow implementing classes locally, so you have to declare the class explicitly (MyOverridenObject in the code above) and then use:
// Finally, you can assign an overriden class to the private field
private MyObject myObject = new MyOverridenObject();
so I know you can Override methods in Object's declaration
This isn't object declaration but class instantiation. And this feature doesn't exist in C# .
Therefore, you can only override polymorphic methods on class declarations:
public class A
{
public virtual void DoStuff() {}
}
public class B : A
{
public override void DoStuff() {}
}
I was fiddling with Java 8 and came down to the following code which in my opinion could work:
class UnrelatedClass implements UnrelatedInterfaceDefault {
#Override
public void unrelate2() {
System.out.println("Unrelated");
}
}
interface UnrelatedInterfaceDefault extends UnrelatedInterfaceOne, UnrelatedInterfaceTwo {
default public void unrelate() {
UnrelatedInterfaceOne.super.unrelate2();
UnrelatedInterfaceTwo.super.unrelate2();
}
}
interface UnrelatedInterfaceOne {
public void unrelate2();
}
interface UnrelatedInterfaceTwo {
public void unrelate2();
}
On UnrelatedInterfaceOne.super.unrelate(), I get the error:
abstract method unrelate2() in UnrelatedInterfaceOne cannot be accessed directly.
But consider if I would create a class that implements UnrelatedInterfaceDefault, then I actually do have implementations for UnrelatedInterfaceOne and UnrelatedInterfaceTwo, so it could work?
Why is there this specific compiler error in this case?
This is failing because the methods in your interfaces are abstract. If you make it default, then I guess it would compile. I can't test it right now though.
From JLS ยง15.12.3 - Compile-Time Step 3: Is the Chosen Method Appropriate?:
If the form is TypeName . super . [TypeArguments] Identifier, then:
It is a compile-time error if the compile-time declaration is abstract.
Also note that, invocation of a method using super never goes through dynamic dispatch. It wouldn't invoke the overridden method, but only the method defined in the super class, or in this case TypeName.
I tried to make your example work.
As noted #Rohit Jain I needed to change abstract-> default. Then I've got a diamond problem right in interface UnrelatedInterfaceDefault. I resolved it with empty method.
That's all, it works. As for me, results are logical) see below
public class Main {
public static void main(String[] args) throws IOException, Exception {
UnrelatedClass uc = new UnrelatedClass();
uc.unrelate2();
uc.unrelate();
}
}
class UnrelatedClass implements UnrelatedInterfaceDefault {
#Override
public void unrelate2() {
System.out.println("Unrelated");
}
}
interface UnrelatedInterfaceDefault extends UnrelatedInterfaceOne, UnrelatedInterfaceTwo {
#Override
public default void unrelate2() {
}
default public void unrelate() {
UnrelatedInterfaceOne.super.unrelate2();
UnrelatedInterfaceTwo.super.unrelate2();
unrelate2();
}
}
interface UnrelatedInterfaceOne {
public default void unrelate2() {
System.out.println("relatedOne");
}
}
interface UnrelatedInterfaceTwo {
public default void unrelate2() {
System.out.println("relatedTwo");
}
}
Output:
Unrelated
relatedOne
relatedTwo
Unrelated
I have a basic question about generics in Java.
I have a class X which is instantiated by another class T. In every class T which will be used has a method called as methodOfT(). However, Java gives me compiler time error since it does not know obj and methodOfT().
public class X<T>
{
T obj;
public void methodOfX()
{
obj.methodOfT();
}
}
In order to avoid this problem, what I did is I defined another class XSuper. And every class now which wants to instantiate X will extend this XSuper class. This removes the compile time error and allows me to achieve what I want.
public abstract class XSuper
{
public abstract void methodOfT();
}
public class UserOfX extends XSuper
{
X<UserOfX> objX = new X<UserOfX>();
public void methodOfT()
{
}
}
However, I want to know the cleaner way of doing this thing. Since I want to derive class UserOfX from another Class. Another Problem is that I want to define methodOfT() method as -
public methodOfT(T objOfT)
{
}
In this case, the above solution fails. Could someone help.
public class X<T>
{
T obj;
public void methodOfX()
{
obj.methodOfT();
}
}
The compiler doesn't know what T is so it is evaluated as Object. Object does not have a methodOfT method, so compilation fails. Here's how to solve that:
public interface SomeInterface{
void methodOfT();
}
public class X<T extends SomeInterface>
{
T obj;
public void methodOfX()
{
obj.methodOfT();
}
}
In this case, the compiler knows that the supplied T will implement the interface SomeInterface and hence have the method methodOfT. (You can also use classes instead of interfaces, but that's less elegant)
Given your additional requirements, we're going t have to change this code some more:
public interface SomeInterface<X>{
void methodOfT(X object);
}
public class X<T1, T2 extends SomeInterface<T1>>
{
T1 obj1;
T2 obj2;
public void methodOfX()
{
obj2.methodOfT(obj1);
}
}