EDIT: FORGOT THE CODE SNIPPET _ ADDED HERE
I am trying to learn Java from the book 'Learning Java' that has the following code snippet listed as an example for interface callbacks. In this code snippet, there is only 1 class implementing the interface TextReceiver. My question is - since this code is instantiating the interface directly, if there was another class that implemented the interface TextReceiver and provided a whole different method body to the interface method receivetext than the one in TickerTape, then how would java resolve the reference to the method receivetext in the sendText method of TextSource? This seems like it would introduce ambiguity - also, it seems credence to what I have seen online about not being able to instantiate interfaces - but wanted to confirm before assuming
interface TextReceiver {
void receiveText( String text );
}
class TickerTape implements TextReceiver {
public void receiveText( String text ) {
System.out.println("TICKER:\n" + text + "\n");
}
}
class TextSource {
TextReceiver receiver;
TextSource( TextReceiver r ) {
receiver = r;
}
public void sendText( String s ) {
receiver.receiveText( s );
}
}
I tried just writing this up myself to figure this out, but got stuck with issues compiling since all of these classes were in the same class. I know this sounds n00bish - but I figured you guys might have quick guidance to offer.
Thanks in advance!!!
Methods are dispatched at runtime by looking at the actual type of the object instance.
So if you have
TextReceiver one = new SomeTextReceiver();
TextReceiver two = new SomeCompletelyDifferentTextReceiver();
and then call
one.receiveText();
the JVM will look at the actual object and see what class it is of.
The call will be dispatched to the implementation provided by that runtime class.
At compile-time all that is known here is the interface, so the compiler will check that such a method exists in the interface, but at run-time the actual class can be determined and dispatched to.
Note that this process is different for static methods. Those do not have an associated instance and the compiler does decide which implementation to call. As a result, you cannot really override static methods to get runtime dispatch.
Java interfaces cannot be instantiated, the programmer has to specify what implementation of the interface he wants to instantiate.
For example, if you try to do this (replace INTERFACE with the name of the interface):
INTERFACE i = new INTERFACE();
you will get an error, because an interface cannot be instantiated.
What you must do is (replace IMPLEMENTATION with the name of the implementation of the interface):
INTERFACE i = new IMPLEMENTATION();
As you can see, you ALWAYS tell the program what implementation to use for an interface. There's no room for ambiguity.
In your example, the class TextSource is NOT instantating the interface TextReceiver (instantiation occurs with the "new" keyword). Instead, it has a constructor that receives the implementation of the interface as a parameter. Therefore, when you call TextSource you MUST tell it what implementation of TextReceiver to use.
Related
I was going through a java tutorial on Spring Retry and there I read about RetryCallback, which is an interface.
In the same tutorial, I found this chunk of code:
retryTemplate.execute(new RetryCallback<Void, RuntimeException>() {
#Override
public Void doWithRetry(RetryContext arg0) {
myService.templateRetryService();
...
}
});
The way I see it, an anonymous object of RetryCallback is being instantiated. But then we just read it's an interface.
Could someone explain what's happening here?
Although not required, but just in case here's a link to the tutorial
This:
new RetryCallback<Void, RuntimeException>() {
#Override
public Void doWithRetry(RetryContext arg0) {
myService.templateRetryService();
...
}
}
is an anonymous class. When this code is run, an object of class MyContainingClass$1, which implements RetryCallback, instantiated.
When instantiated within an instance method, anonymous classes have an implicit reference to the MyContainingClass instance, which is accessed via the syntax MyContainingClass.this.
Note that the 1 in the class name is actually n where the anonymous class is positioned nth relative to all anonymous classes in the containing class.
its just providing a inline implementation for that interface, its not instantiating the interface. its equivalent of creating a new class a that implements RetryCallback, and passing to to execute
The question written in the title of your post:
Is it possible to instantiate an interface in java?
No, it is not possible. From 4.12.6. Types, Classes, and Interfaces in JLS (bold emphasis added by me):
Even though a variable or expression may have a compile-time type that is an interface type, there are no instances of interfaces. A variable or expression whose type is an interface type can reference any object whose class implements (ยง8.1.5) that interface.
I have a method (prepareErrorMessage) that accepts objects of type ErrorMessagePojoSuperclass. However, I only pass subclasses of ErrorMessagePojoSuperclass as arguments:
public class ErrorMessagePojoBundle extends ErrorMessagePojoSuperclass {}
public class Tester {
ErrorMessagePojoBundle empb = new ErrorMessagePojoBundle();
prepareErrorMessage(empb);
public void prepareErrorMessage(ErrorMessagePojoSuperclass errorMessagePojo) {
String errorStatusMsg = messageConverter.convertXMLToString(errorMessagePojo);
}
}
The class ErrorMessagePojoBundle has more methods than its superclass.
I need to make sure that when the line of code is running messageConverter.convertXMLToString(errorMessagePojo), messageConverter processes an instance of the subclass - in this case the object empb. Any ideas? I want to solve this without the use of casting. Thank you.
Any ideas? I want to solve this without the use of casting.
Your options are:
Defining an interface with the necessary method, having the subclass implement it, and using that interface as the parameter type rather than the superclass.
Changing the parameter type to the subclass, not the superclass.
instanceof and casting (not usually what you want to do).
1 and 2 are basically just variants of each other.
In your example code, there's no reason for prepareErrorMessage to accept the superclass rather than the subclass (or an interface), since the only thing it does can only be done with the subclass (or something implementing the same interface).
I need to add one optional method in existing abstract class that is extended by more than 50 classes:
public abstract class Animal{...}
This method is not used by all those classes, but in the future it probably will.
The structure of one of my classes is:
public class Dog extends Animal {...}
The cleanest way is using abstract method but it obliges me to change all existing classes.
The workaround is to create "empty" method in abstract class:
public String getString(Map<String, Object> params){
return "";
}
and then override it when I need in classes that extend abstract class.
Is there any better solution?
Having an "empty" method is fine. But in order to be sure, that it will be implemented where it is really needed, consider throwing an exception by default from this method:
throw new UnsupportedOperationException();
A similar approach is used in java.util.AbstractList class:
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
I can't help feeling like you have some architectural/design issues here, but without knowing more, I can't say for sure. If 50 classes are going to inherit from Animal, but not all of them are going to use this method, then I'm wondering if they should really inherit from one common class. Perhaps you need further levels of sub-classing... think Kingdom->Phylum->Sub-Phylum. But my gut says that's still not the right answer for you.
Step back - what are you trying to accomplish? If you're going to implement this function on these classes in the future, then you must also be changing your code to know to use/expect this. The point of inheritance is to allow code to refer to an object's expected common behavior without knowing what type of object it's referencing. In your getString() example, you might have a function as such:
public string SendMessage(Animal someAnimal) {
string message = someAnimal.getString();
// Send the message
}
You can pass it a dog, a cat, a platypus - whatever. The function doesn't care, because it can query the message from its base class.
So when you say you'll have animals that don't implement this message... that implies you'll have logic that ensures only cats and dogs will call this function, and that a platypus is handled differently (or not at all). That kind of defeats the point of inheritance.
A more modern approach would be to use interfaces to establish a "has a" relationship instead of an "is a" relationship. A plane might have an IEngine member, but the specific type of engine can be set at run-time, either by the plane class itself, or by the app if the member is writeable.
public interface IEngine {
string getStatus();
string getMileage();
}
public class Cessna {
public IEngine _engine;
public Cessna() {
_engine = new PropellerEngine();
}
}
You could also inherit directly from that interface... Animals that don't implement IAnimalMessage wouldn't implement that function. Animals that do would be required to. The downside is that each animal will have to have its own implementation, but since your base class currently has an abstract function with no body, I'm assuming that's a non-issue. With this approach, you can determine if the object implements the interface as such:
IAnimalMessage animalMessage = myPlatypus as IAnimalMessage;
// If your playtpus doesn't implement IAnimalMessage,
// animalMessage will be null.
if (null != animalMessage) {
string message = animalMessage.getString();
}
public interface IAnimalMessage {
string getMessage();
}
public class Platypus : IAnimalMessage {
// Add this implementation when Platypus implements IAnimalMessage...
// Not needed before then
public string getMessage() {
return "I'm a cowboy, howdy, howdy, howdy!";
}
}
That's probably the closest to what you're asking for I can suggest... classes that don't need the message won't implement that interface until they do, but the code can easily check if the interface is implemented and act accordingly.
I can offer more helpful/specific thoughts, but I'd need to understand the problem you're trying to solve better.
I am coming from Java background and currently learning C#. I just had a big surprise regarding (what I perceive as ) a difference in a way that an object accesses methods from base/derived class. Here is what I mean:
In Java if I do something like this
class InheritanceTesting
{
public void InheritanceOne()
{
System.out.println("InheritanceOne");
}
}
class NewInherit extends InheritanceTesting
{
public void InheritanceOne()
{
System.out.println("InheritanceTwo");
}
}
then run the following:
public static void main(String[] args) {
InheritanceTesting inh = new NewInherit();
inh.InheritanceOne();
}
I get the result:
InheritanceTwo
If I do exactly the same in C#:
class InheritanceTesting
{
public void InheritanceOne()
{
Console.WriteLine("InheritanceOne");
}
}
class NewInherit : InheritanceTesting
{
public new void InheritanceOne()
{
Console.WriteLine("InheritanceTwo");
}
}
Then:
InheritanceTesting inh = new NewInherit();
inh.InheritanceOne();
result is
InheritanceOne
I remember being taught in Java that "object knows what type it is instantiated to", therefore, no surprises when I call the overridden method. Does this mean that the situation is the opposite in C#? Object only "knows" its declared type? If so, what is the logic/advantage in that? It seems to me that Java treats base classes like interfaces - here is your type and here is your actual implementation. I am new to C# and maybe I am missing something obvious here?
A slightly more interesting case is the following
class InheritanceTesting
{
public void InheritanceOne()
// Java equivalent would be
// public final void InheritanceA()
{
Console.WriteLine("InheritanceA - One");
}
public virtual void InheritanceB()
// Java equivalent would be
// public void InheritanceB() // note the removing of final
{
Console.WriteLine("InheritanceB - One");
}
}
class NewInherit : InheritanceTesting
{
public new void InheritanceOne()
// There is no Java equivalent to this statement
{
Console.WriteLine("InheritanceA - Two");
}
public override void InheritanceB()
// Java equivalent would be
// public void InheritanceB()
{
Console.WriteLine("InheritanceB - Two");
}
}
What you are seeing are some of the difference between C# and Java, you can get C# to behave like Java as the method InheritanceB will show.
C# methods are final by default, so you need to take a positive action to make it possible to override a method by marking it as virtual. So the virtual method InheratanceB will behave like you expect methods to behave, with method dispatch based on the object type, not the reference type. e.g.
NewInherit example = new NewInherit();
InheritanceTesting secondReference = example;
example.InheritanceB();
secondreference.InheritanceB();
Will both produce InheritanceB - Two as the method InheritanceB was virtual (able to be overriden) and overridden (with the override method).
What you where seeing is called method hiding, where the method can not be overriden (non-virtual) but can be hidden, hidden methods are only hidden when the reference (not the object) is of the derived type so
NewInherit example = new NewInherit();
InheritanceTesting secondReference = example;
example.InheritanceA();
secondreference.InheritanceA();
Will produce InheritanceB - Two first and InheritanceB - One second. this is because (at least in the simple cases) invocation of final methods is bound at compile time based on the reference type. This has a performance benifit. Binding of virtual methods needs to be differed to runtime as the compiler may not be aware of the instances class.
In practice method hiding is not widely used, and some organisation have coding standards forbidding it. the normal practice is to mark the methods you expect a sub-class to be able to override as virtual and in the sub-class use the keyword override.
More directly answering your questions
Does this mean that the situation is the opposite in C#? Object only
"knows" its declared type?
No, c# knows both the constructed type (instance) and the declared type (reference). It uses the instance type for overridden methods and the declared type for final methods even if the instance has hidden the method.
If so, what is the logic/advantage in that?
No the case, I believe there are performance benefits in binding at compile time where possible, e.g. allow in-lining of methods. Also as explained there is not a loss of flexibility as you can have the same behaviour as Java by using the virtual and override keywords.
Java treats methods as virtual by default, C# methods are non-virtual by default. If you want the same behavior in C# use the virtual keyword. In Java you can use final to ensure an inherited class doesn't override a method.
The reason C# methods are not virtual by default is most likely to prevent people from being able to change every inherited functions behavior on the fly in ways the base class designer didn't intend. This gives more control to the base class designer and ensures that inheritance is carefully and willfully planned for rather than just done on the fly.
Java makes methods virtual by default, while in C# you have to explicitly enable virtual inheritance.
That's why you added the new modifier right? Because you got a warning about it? That's because without a method being virtual, you replace it statically if in a derived class you redefine it. If instead of calling InheritanceOne() through a base pointer you call it through a derived pointer you'll get the result you expect -- the compiler chooses non-virtual methods at compile time, based on compile time only information.
TL;DR: Anytime you want to use inheritance for a method, make it virtual in C#. new is one of the worst things in the language for methods, it has no real use and only adds gotchas to your code.
You might think that you have written the same thing (same words), though you did not (you used new keyword in c# version) but C# equivalent of what you wrote in Java is this.
class InheritanceTesting
{
public virtual void InheritanceOne()
{
Console.WriteLine("InheritanceOne");
}
}
class NewInherit : InheritanceTesting
{
public override void InheritanceOne()
{
Console.WriteLine("InheritanceTwo");
}
}
In Java, by default all methods, except privates and statics of course, are virtual and any method has same signature with a super class method is an override.
By default, every method in Java can be overridable by its sub classes(unless private/static etc).
In C#, you have to make a method virtual if it has to be overriden by sub classes.
In your C# example, its not a overriden method so the behaviour is expected.
I need to write a function that accepts an object , but I want to enforce in the function call (not after the function is called) that the object is an interface.
Meaning , I want to make sure this is an Interface at compile time , not on run time.
What do I mean?
interface ISomething {...}
class A implements ISomething { ... }
ISomething something = new A();
MyClass.register(something);
In this example , the passed object is an interface , and I want that the MyClass.register function to enforce the this requirment in it's declaration.
I don't know which interface I'm going to get , and there is no use defining another interface to be implemented by all other implementation , because I need the real interface.
To accept only objects that implement an interface as argument, use the interface as type, i.e.:
void acceptMaps(Map argument) {
}
can be called with objects implementing the Map interface, like HashMap but not with Strings for instance as they do not implement Map.
Is this what you meant with your question?
Edit in this example, objects implementing SortedMap which extends Map are accepted too, so in your case you could create a BaseInterface and extend that in the interfaces (like AcceptedInterface extends BaseInterface) you want to be accepted by your .register(BaseInterface arg) method.
You can't instantiate an interface so you would never be able to create one to send in. You can specify an interface in the parameters for the function and only objects which implement that interface can be passed in. But there is no way to require an interface be what is passed in because you can't create them.
I think you need to rethink what you're trying to accomplish.
You're making a distinction between the type of the object (in this case A) and the type of the reference to the object (in this case ISomething).
Sounds like you want to permit this code:
ISomething something = new A();
MyClass.register(something);
but forbid this code:
A something = new A();
MyClass.register(something);
I don't think you can achieve this with Java.
Let me see if I understand.
Do you want to check at compile time that the argument passed to a function is some interface? Any interface?
If that's the question, the answer is you can't.
I don't know which interface I'm going to get [...] I need the real interface.
You can't actually validate if you don't know which type to expect.
In Java you need to know the type to validate the parameter, the argument must be of the same type or a descendant, Java doesn't make distinctions on this regard at compile time, you can make it at runtime as Daff aswered.
You can ask the class of the object you get interfaces it implements during runtime.
If you can't already give the compiler the types of the interfaces you expect it has no way to predict what is going to be passed into your method so you will have to use runtime reflection.
There's no way to check at runtime, if the 'object is an interface' because an object can never ever be 'an interface', it only be an instance of a class that implements an interface.
And it's not possible to restrict a method signature to interface usage, say you'll allow type 'Animal' but not type 'Dog' which implements animal behavior. (I guess that's what you were looking for)
Taking your example - you want a compiler error for this implementation:
interface ISomething {...}
class A implements ISomething { ... }
ISomething something = new A();
MyClass.register(something);
A unwanted = (A) something;
MyClass.register(unwanted); // <- compilation error here
But practically spoken - I see no immediate reason. If you want to enforce programmers to use interfaces - user code inspection or quality check tools. If you want to restrict instantiation of an implementation, protect the constructor and use a factory to produce instances.
"The object is an interface" doesn't make sense. It seems like you want to enforce that the pointer passed into the function was declared with an interface type like
Interface_t x = new Class_which_implements_interface_t();
as opposed to
Class_which_implements_interface_t y = new Class_which_imlements_interface_t();
The only problem is that if you make a function like this:
void some_func(Interface_t z) {...}
And you call it with some_func(x); or some_func(y); the function is passing the reference by value, which means that inside of some_func, z is a copy of x or y which has been casted to an Interface_t pointer. There is no way to get information about what type the original pointer had. As long as it is able to be casted to an Interface_t it will compile and run.