Using interface type in a class - java

I'm trying to understand this concept. Where Path type is being created using Paths's class method.
I have two doubts:
How can we have Path type in class we are creating without any Path interface reference in a class (For ex, implements).
Code snippet:
Path dir = Paths.get(args[dirArg]);
The class where I have found this snippet, there is no implementation of Interface Path.
Imported packages in class:
import java.nio.file.*;
import static java.nio.file.StandardWatchEventKinds.*;
import static java.nio.file.LinkOption.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.util.*;
In class how can we create a method which returns Interface type. For ex Paths's class get method. In Paths class there is no link that is connected to Path interface. So how its defined in Java ? How can I understand this ?
Please put some light on me...!

The get-method you call will create (and return) an implementation of your interface.
Let's say you have an interface Action:
public interface Action {
void doSomething();
}
and you have a call:
Action action = X.getAction();
With the following X-class:
public class X {
public Action getAction() {
return new Action() {
public void doSomething() {
System.out.println("done");
};
}
}
So, even though there isn't a specific class that implements Action, the getAction() method returns an (anonymous) class that implements your interface.
The code is not all that different if there is a class implementing your interface: at that point, the getAction() method might return an instance of that class.

How can we have Path type in class we are creating without any Path interface reference in a class (For ex, implements).
The real answer is, you don't need to care.
The get method returns some kind of object that implements Path, that's for sure. And you don't need to know any more information about what kind of path that is. All your code need to know is that it returns a Path, end of story.
From the outside you might not see a class that implements Path, but in fact there must be one. It's just that you don't know.
It is, however, possible to get the actual type of Path returned.
System.out.println(Paths.get("/Users/").getClass()); // getClass returns the type
This prints class sun.nio.fs.UnixPath, which does not seem to be a public class.
In class how can we create a method wich returns Interface type. For ex Paths's class get method. In Paths class there is no link that is connected to Path interface. So how its defined in Java ? How can I understand this ?
You certainly can create a method with an interface return type!
interface MyInterface { ... }
class A implements MyInterface { ... }
class B {
public static MyInterface myMethod() {
// obviously you can add more logic than this, this is just an example
return new A();
}
}
Now as a caller of that method,
MyInterface i = B.myMethod(); // you don't (need) know what actual type of object "i" is.

Related

Java +Strategy + Factory + same package = how to hide specialized classes?

I want to hide the specialization classes from the external classes of the same package.
Example:
package com.app.letter;
public interface LetterChange {
void change();
}
public class A implements LetterChange{
public void change(){..}
}
public class B implements LetterChange{
public void change(){..}
}
To instantiate these classes I use a factory....
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
Note, all of them are in the same package and I DO NOT WANT to put the factory and the specialized classes in a sub package and change the specialization classes' constructors to default (package).
Following this example, I have a third class in the same package
package com.app.letter;
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(null); // Legal
new A(); Illegal
new B(); Illegal
}
}
I want to provide the A or B only by the factory LetterFactory.getInstance(doesNotMatter) which is in the same package.
Make A and B private static classes of the factory:
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
return doesNotMatter.isA() ? new A() : new B();
}
private static class A implements LetterChange{
public void change(){..}
}
private static class B implements LetterChange{
public void change(){..}
}
}
Only the factory knows the existence of these classes and can instanciate them.
First of all, I see no reason to not allow to instantiate your classes directly. Usually, you do not care who instantiated the class, as long as you are sure it was instantiated correctly.
Therefore, I believe you have not one problem, but two:
Provide a way for anyone to correctly create both class A and class B manually, if required.
Provide a way to instantiate either A or B given some set of abstract parameters (your Factory solution).
As for the first part, the are 3 ways to instantiate classes of different complexity correctly:
A constructor, which has a list of all required parameters and dependencies. This can be used for simple cases pretty well.
A factory method. This can be used for more complex scenarios.
A factory class/a builder class. These are usually used for complex scenarios.
Now, whichever one you choose, by all logic it should be allowed to be public. The constructor/factory method/factory class will enforce your rules to create a proper valid instance of either A or B. And, as I mentioned before, there is no possible scenario when you should disallow creating a perfectly good and valid instance of a class.
Let's say you went with a builder class as the most complex solution. Here's how your code might look:
package com.app.letter.A;
public class A {
A() { //Package visibility, we don't want anyone to create an invalid A class
...
}
...
}
public class ABuilder {
public void validateAndSetSomeCriticalParam(Param param) {
...
}
public A build() {
A a = new A();
a.setSomeCriticalParam(param);
...
return a;
}
}
The builder should be designed in a thought in mind, that it could not in any way produce an invalid instance of A. This way, you can allow the builder to be the only way of instantiating A and not worrying about it, because all instances it creates are always valid. You can utilize proper API on the builder or Exceptions to reach this.
Also, the builder approach is the most complex one, for some simpler scenarios you might use a bunch of public static factory methods. However the idea should remain the same - the public factory methods should ensure that they produce only valid instances of A.
Same stuff for B class, in other package:
package com.app.letter.B;
public class B {
...
}
public class BBuilder {
...
}
Now for the factory. Basically same thing you had, but with builders:
package com.app.letter;
public class LetterFactory{
public static LetterChange getInstance(Object doesNotMatter){
if (doesNotMatter.isA()) {
ABuilder builder = new ABuilder();
builder.setSomeCriticalParam(...);
builder...
return builder.build();
} else {
BBuilder builder = new BBuilder();
builder.setSomeBSpecificParam(...);
builder...
return builder.build();
}
}
}
And about the usages:
public class DoesNotMatterClass{
public void situations(){
LetterFactory.getInstance(..whatever..); // Legal
new A(); //Illegal, as it is package protected
new B(); //Illegal, as it is package protected
new ABuilder(); //Legal, as ABuilder can ensure that only valid As are created
new BBuilder(); //Legal, as BBuilder can ensure that only valid Bs are created
}
}
I will add, repeating myself once again, you should only hide the parts of your system that can be abused in some ways. There is no point of hiding a class or a method if there is no way for it to be abused. Therefore, if you provide a way to correctly initialize a valid instance of A or B it should not matter to you that some other part of the system can see it or use it.
You can hide A and B from other packages by making them package-protected.
But that won't hide them from classes in the same package.
Since they have to be visible by the factory, but not by any other class of the same package, the only way to do that is to make them private static nested classes of the factory class.

import class in different directory

Actually, I am trying to finish this practice in "Think in Java" for self-learning purpose --
Exercise 6: (2) Create an interface with at least one method, in its own package. Create a
class in a separate package. Add a protected inner class that implements the interface. In a
third package, inherit from your class and, inside a method, return an object of the
protected inner class, upcasting to the interface during the return.
so I created a class named IgetResult.java under directory "a" which has a IIGetResult Interface.
interface IIGetResult {
String getResult();
}
public class IgetResult {
}
then I create another class in another directory -- directory b
import a.IgetResult.IIGetResult;
public class PracticeClass {
protected class inner implements IIGetResult {
#Override
String getResult(){ return "result";}
}
public static void main(String[] args) {
System.out.println("practice start");
}
}
In the final step, I compile the two java classes with command:
# javac a/.java b/.java
and get the following error:
./a/IgetResult.java:1: duplicate class: IIGetResult
interface IIGetResult {
^
./a/IgetResult.java:4: duplicate class: IgetResult
public class IgetResult {
^
b/PracticeClass.java:1: cannot access a.IgetResult
bad class file: ./a/IgetResult.java
file does not contain class a.IgetResult
Please remove or make sure it appears in the correct subdirectory of the classpath.
import a.IgetResult.IIGetResult;
^
Please teach me go through this practice, thanks in advance.
As per the quote:
Create an interface with at least one method, in its own package.
So we create IGetResult.java file in folder a:
package a;
public interface IGetResult {
String getResult();
}
Create a class in a separate package. Add a protected inner class that implements the interface.
Now we create a class in a separate package (folder), with inner class which implements the interface:
package b;
import a.IGetResult;
public class InnterTest {
protected class GetResultImpl implements IGetResult {
#Override
String getResult() { return "result"; }
}
}
In a third package, inherit from your class and, inside a method, return an object of the protected inner class, upcasting to the interface during the return
So now we create a sub-class of InnerTest class in third separate package:
package c;
import a.IGetResult;
import b.InnterTest;
public class InnerTestSubclass extends InnerTest {
public IGetResult getResultClass() {
//Up-casting happens automatically since GetResultImpl is sub-class of IGetResult
return new GetResultImpl();
}
}
I typed it by hand, but you should get the idea. Hope that helps.
I can see the following issues:
You are missing the 'package <a/b/c>' declaration in your classes.
Your a.IIGetResult interface should be public, otherwise it won't be visible in the 'b' package.
The Java convention is for class name to start with an upper case, thus your inner class insided PracticeClass should be named 'Inner' instead.
Your inner class should have a public constructor, so that the later can be invoked from a class extending PracticeClass defined in another package.
The overriden inner.getResult() method should be public (but out-of-topic).
Your class IGetResult should be defined in a third package (c?) and should extends PracticeClass (though I must admit your instructions are a little bit confusing to me).
Aplly the above points along with #dimoniy's answer and you should be OK.
Your class needs to be inside of your interface. This needs to be in a file called IIGetResult.java
interface IIGetResult {
String getResult();
public class IgetResult implements IIGetResult{
#Override
String getResult() { return null; }
}
}

Why getClass returns the name of the class + $1 (or $*)

I'm writing a piece of code in which I have to cast an Object if it is an instance of a certain class.
As usual I'm using instanceof for checking the compatibility.
The problem is that the check is never satisfied because the objects belong to "strange" classes.
For example; when I call the method getClass().getSimpleName() on this object it return me the name of the class + $* (e.g. ViewPart$1 instead of ViewPart).
What does this $* means?
Is there a solution or a workaround?
That shows an inner class (either anonymous (if it has a number) or named). For example:
class Foo {
static class Bar {
}
}
The name of class Foo.Bar is Foo$Bar. Now if we had:
class Foo {
static void bar() {
Runnable r = new Runnable() {
public void run() {};
};
System.out.println(r.getClass());
}
}
That will print Foo$1.
You can see the same effect in the naming of the class files created by javac.
These are instances of an anonymous class. ViewPart$1 is the first anonymous class defined inside ViewPart - but that doesn't mean it's a subclass of ViewPart. It's most likely an anoymous implementation of some Listener interface.
$ denotes for inner class. For example consider two classes
public class TopClass {
class SubClass {
// some methods
}// inner class end
} // outer class end
If you compile this code you will get two class files TopClass.class and TopClass$SubClass.class.
Check your ViewPart class whether it has any inner classes.
Hope it helps.

This appears to create an object from an interface; how does it work?

interface Int {
public void show();
}
Int t1 = new Int() {
public void show() {
System.out.println("message");
}
to.show();
You're defining an anonymous class that implements the interface Int, and immediately creating an object of type thatAnonymousClassYouJustMade.
This notation is shorthand for
Int t1 = new MyIntClass();
// Plus this class declaration added to class Test
private static class MyIntClass implements Int
public void show() {
System.out.println("message");
}
}
So in the end you're creating an instance of a concrete class, whose behavior you defined inline.
You can do this with abstract classes too, by providing implementations for all the abstract methods inline.
What this special syntax for anonymous inner classes does under the hood is create a class called Test$1. You can find that class file in your class folder next to the Test class, and if you printed t1.getClass().getName() you could also see that.
i think your object has nothing to do with the interface. If you comment out the whole interface, still you will get the same output. Its just anonymous class created. I think, unless you use the class "implements" you cant implement the interface. But i dunno how naming collision doesn't happen in your case.

How do you get the Class of an Abstract class (Object) in JavaME?

I need to get the Class of an object at runtime.
For an non-abstract class I could do something like:
public class MyNoneAbstract{
public static Class MYNONEABSTRACT_CLASS = new MyNoneAbstract().getClass();
But for an abstract class this does NOT work (always gives me Object)
public abstract class MyAbstract{
public static Class MYABSTRACT_CLASS = MyAbstract.class.getClass();
This code will be running in JavaME environments.
You just need
MyAbstract.class
That expression returns the Class object representing MyAbstract.
The code you want in the abstract case is:
public abstract class MyAbstract{
public static Class MYABSTRACT_CLASS = MyAbstract.class;
}
although I personally wouldn't bother defining the constant and just used MyAbstract.class throughout.
I would have expected the code you wrote to have returned the class 'Class', not the class 'Object'.
I think more information is required here.
In Java, an abstract class cannot be instantiated.
That means an Object at runtime cannot have its class be abstract.
It would need to be a subclass that implements all abstract methods.
In JavaME, Object.getClass() should be all you need.
Are you somehow trying to reconstitute your class hierarchy at runtime?
In that case, you could implement something like this instead:
public String getClassHierarchy() {
return super.getClassHierarchy() + ".MyAbstract";
}

Categories

Resources