A co-worker came to me with a question and it made me think of this recent thread, although this one didn't quite hit on the exact question I have. What is the usefulness of writing this:
I understand the use of interface references when it comes to method parameters and in the realm of polymorphism, but, when you're creating the object, I don't see what the point of storing it in an interface reference is. Any time you try to use that object in a place where an interface reference is expected, the object will simply be implicitly casted by the compiler. Take the following example:
In this example, both calls to foo will compile just fine and, in the second case, the ArrayList will be implicitly cast into a List so that it can be used in the method foo. What I'm really getting at is why would you ever want to use the first line rather than the second line? Let's look at another example. Assume you have a factoy which can create an object that implements FactoryObject. Then, I see the use of being able to assign to an interface reference type.
However, in this case, we're not using new to create an object - the Factory class is doing that for us. Let's look inside the factory class, however:
There's no reason to assign the object that was really created, or cast it as a FactoryObject. The compiler will do that for you. Granted, the previous method could be rewritten like this, in order to follow a more "accepted" programming style.
This is a case where using an assignment to an interface reference is useful, but only for greater readability. It is prefectly legal to bypass the assignment, as shown above. So, now that I've shown a case where assigning an object to an interface reference was "pseudo-useful," let's look at a case where it might be detrimental. If a (non abstract) class implements an interface, you are guaranteed that the class is question will implement all of the methods of that interface. However, you are not guaranteed that the class in question won't provide extra functionality, like this:
Now, assuming that this is the case, take a look at this code, which tried to use an object of type InterfaceAImplementor:
As you can see, after assigning the object to an interface reference type, we've "narrowed" our view into the object and what it can do. In order to get access to the methods that we need to call, we'd have to case it as the original object first. So, what I'm really getting at is that a lot of people seem to think that you should assign an object to an interface reference rather than to a reference to the class the object is a type of whenever possible. I don't understand why, in general, this is a good practice. If anything, I find it more detrimental, than beneficial. Please do not misinterpret this question. I'm not asking what the usefulness of interfaces is - I'm well aware of how useful they can be. I'm asking, specifically, is it really a good practice to assign an object to an interface reference, is possible. What happens if an object implements multiple interfaces? Then what do you assign it to? Thanks, Corey
[I]What is the usefulness of writing this: [/I] The main advantage comes with code maintenance. For instance, if someone comes and wants to use a LinkedList instead of the ArrayList, you only need to change one line rather than zillions throughout the code. It makes your code a little more flexible. [ February 07, 2002: Message edited by: Marilyn deQueiroz ]
JavaBeginnersFaq "Yesterday is history, tomorrow is a mystery, and today is a gift; that's why they call it the present." Eleanor Roosevelt
Joined: Dec 20, 2001
Originally posted by Marilyn deQueiroz: [I]What is the usefulness of writing this: [/I] The main advantage comes with code maintenance. For instance, if someone comes and wants to use a LinkedList instead of the ArrayList, you only need to change one line rather than zillions throughout the code. It makes your code a little more flexible. [ February 07, 2002: Message edited by: Marilyn deQueiroz ]
No it doesn't. That would be the case if every method call that we used required an ArrayList rather than a List. I'm talking, specifically, about when the object is created. If this was the case:
However, I'm talking about a situation where you have:
This code will work just fine (because of the implicit upcast) and, if sometime down the road, you decide that you want to use an ArrayList, you can change just line 1 to read:
That's not really what I'm asking. What I want to know is, why is it seen as good practice to write line 1 like this:
rather than like this:
Please take a close look at my original post again. Thanks, Corey
Originally posted by Corey McGlone: I'm asking, specifically, is it really a good practice to assign an object to an interface reference, is possible. What happens if an object implements multiple interfaces? Then what do you assign it to? [/QB]
IMHO, in general, it is good practice to use interface references. Granted, there are situations where you shouldn't use interfaces ( Joshua Bloch explains what some of these situations are in his book "Effective Java Programming Language Guide" -- highly recommended that you get your hands of a copy of this). One key element of a good maintainable design is loose coupling between the different parts of the application. Decoupling the requirements from the implementation promotes flexibility. Allen Holub once wrote that objects are really a collection of capabilities. If you write your client code such that it is only concerned with the capabilities guaranteed by an interface rather than the actual implementation by a particular class, you will have more freedom to change implementations in the future. The best example of this I can think of are EJBs. Theoretically, if you stick to the J2EE standard for EJBs and use interfaces exclusively, you should be able to easily port your code from one app server to another. For the most part, this is true of the Java code. (Other components of a J2EE app may not be as easy to port but that's another story). Because the EJB API consists mostly of interfaces, you are guaranteed specific behavior from the underlying EJB container. On the other side of the coin, app server implementors are free to do whatever they deem necessary to provide the guaranteed behavior. If an object happens to implement many different interfaces, then you would simply use the interface reference type that is appropriate for the kind of behavior or capability that you would like to exploit at any particular point in your code. I see nothing hard, confusing, or detrimental about that. Of course, you should always segregrate code that expects specific behavior provided by a particular class from code that expects generic behavior guaranteed by an interface. That is, code like
should really be refactored to:
( darn UBB bug almost made me wipe out my post there for a minute ) [ February 07, 2002: Message edited by: Junilu Lacar ]
Originally posted by Corey McGlone: What I want to know is, why is it seen as good practice to write line 1 like this:
rather than like this:
Maintainability and flexibility are not an issue in your example code. It's only when the use of object references become prevalent in parameters and return types that the problems arise. I suppose it is just better to start "thinking in interfaces" rather than objects from the get go to avoid the tendency to write code that brings these problems about. If you are really only concerned about the capabilities, then you might as well start thinking and writing the code that way. My $0.02
Joined: Dec 20, 2001
Originally posted by Junilu Lacar: Maintainability and flexibility are not an issue in your example code...I suppose it is just better to start "thinking in interfaces" rather than objects from the get go to avoid the tendency to write code that brings these problems about...
This was the basic conclusion that I had come to. I just wanted to know if I was really missing some aspect that would have an effect on maintainability or flexibility. Basically, I'm talking about when the object that implements an interface gets created. If you want an interface reference to point to something, sooner or later, you're going to have to create an object of some class type (unless you want to create anonymous classes everywhere). It's that point of creation I was referring to, as that's the topic my co-worker brought up to me. As far as I can tell, there is no benefit to assigning it to an interface reference than to a reference of the object's type. Although, like you said, Janilu, it might be better to simply "start thinking in interfaces." Thanks, Corey
Marilyn de Queiroz
Joined: Jul 22, 2000
If you have a chance, read chapter 8 of RHE. The authors give a good example showing the benefits of referencing collections with variables of interface rather than class type.