Implementing and using a generic, abstract interface in Java - java

I am tasked with creating a predicate interface and implementing a number of classes that implements that interface. For example, a class called StartsWith is to be generic and needs to have a constructor that accepts any object that is a subclass of CharSequence.
Here is what I currently have:
Predicate.java
package predicates;
interface Predicate<T> {
public char StartsWith(T obj);
}
StartsWith.java
package predicates;
public class StartsWith<T extends CharSequence> implements Predicate<T> {
#Override
public char StartsWith(T obj) {
return 'a';
// TODO Auto-generated method stub
}
}
An example of creating a StartsWith object must look like the following:
StartsWith<String> predicate = new StartsWith<String>("aB");
When I try to instantiate an object like this I am immediately met with an error that says the arguments do not match and for me to provide no arguments in order to make it right, however, it MUST be called this way.
I am confused as to what I am doing wrong here.

This
public char StartsWith(T obj) {
//....
... is a method declaration, not a constructor. I'd in fact call it a "pseudo" constructor since it has the same name as a class. Constructors don't have a return type, not void, not anything.
and here:
StartsWith<String> predicate = new StartsWith<String>("aB");
You call it as if it were a constructor, which again, it is most definitely not.
So,...
Don't give your methods the same names as constructors
Learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
So, for example:
public class FooPredicate {
public static void main(String[] args) {
StartsWith<String> predicate = new StartsWith<String>();
System.out.println(predicate.startsWithMethod("abc"));
}
}
interface Predicate<T> {
public char startsWithMethod(T obj);
}
class StartsWith<T extends CharSequence> implements Predicate<T> {
#Override
public char startsWithMethod(T obj) {
return 'a';
}
}

Related

Java Method that returns different types of generic Lists

I'm currently trying to write a method that goes through a list of Ant-Objects and returns a list of AntScouts, that extend Ant. In general, List<Ant> can contain a lot of different Objects that inherit from Ant.
I also have an enum for the different kinds of ants:
public enum AntType {
QUEEN,WARRIOR,GATHERER,SCOUT;
public Class getClass(AntType type){
return switch (type) {
case QUEEN -> AntQueen.class;
case WARRIOR -> AntWarrior.class;
case GATHERER -> AntGatherer.class;
case SCOUT -> AntScout.class;
};
}
}
This enum causes a warning:
Raw use of parameterized class 'Class'
And this is the method that currently returns a List<Ant>.
public List<Ant> getAntsType(AntType type){
return ants.stream().filter(ant -> ant.getType() == type).toList();
}
How can I write the method so that it get's the AntType enum as argument and returns a List<AntScout> or List<AntWarrior> corresponding to the enum? I REALLY don't want to use Class<T> clazz as argument since that would defeat the point of the enum. (I also use that enum elsewhere, so I can't get rid of it)
How can I write the method so that it get's the AntType enum as argument and returns a List or List corresponding to the enum?
Edit: This comment probably comes closest to the desired solution:
Java Method that returns different types of generic Lists
Use the Power of Polymorphism
How can I write the method so that it get's the AntType enum as argument and returns a List or List corresponding to the enum?
You're overengineering your code for no good reason.
When you're using inheritance, your classes should be designed in a way that allow to benefit from the Polymorphism.
I.e. by using super type Ant for all your objects and interacting with them through overridden behavior without a need to discriminate between the concrete implementations and operating via type casts.
Therefore, your method returning List<Ant> is quite fine.
And even if you wanted to obtain a List<AntQueen> or List<AntScout> as a result of the method execution then you would need a to use a generic type variable T, or rather T extends Ant, and that would imply that you need a mean of representing the T. And enum would not help you with this task because in Java enums can't be generic. You need to provide as a method argument either an instance of T or a Class<T>.
public <T extends Ant> List<T> getAntsByType(Class<T> tClass) {
return ants.stream().filter(tClass::isAssignableFrom).toList();
}
But I would advise sticking with the initial version returning a List of super type Ant declaring method getType() which returns an instance of enum AntType.
public List<Ant> getAntsByType(AntType type) {
return ants.stream().filter(ant -> ant.getType() == type).toList();
}
And as I've said, Java-enums can't be generic, there's no way to obtain Class<T> through it. Hence, you can remove contrived method getClass() from AntType.
public enum AntType {
QUEEN, WARRIOR, GATHERER, SCOUT;
}
Simulated self-type
But if you're still convinced that your application logic require the ability to generate a list of concrete type like List<AntScout> from a list of super type, then you can make use of a recursive type bound.
For that, you need to define the super type as Ant<T extends Ant<T>>.
This approach is also called a simulated self-type idiom and can be observed in the declaration of the parent type of all enums java.lang.Enum<E extends Enum<E>> and in some other parts of the JDK like method Collections.sort(List<T>) where T is defined as <T extends Comparable<? super T>>.
Let's apply self-type idiom for this case.
Consider super type Ant defined as an interface, declaring a self-returning method (you can change into abstract class if you need to declare some skeletal implementations and common fields):
interface Ant<T extends Ant<T>> {
T self();
AntType getType();
}
And here's a couple of concrete classes:
public static class AntWarrior implements Ant<AntWarrior> {
#Override
public AntWarrior self() {
return this;
}
#Override
public AntType getType() {
return AntType.WARRIOR;
}
}
public static class AntScout implements Ant<AntScout> {
#Override
public AntScout self() {
return this;
}
#Override
public AntType getType() {
return AntType.SCOUT;
}
}
That how we can perform conversion using self() method:
#SuppressWarnings("unchecked")
public static <T extends Ant<T>> List<T> getAntsByType(List<Ant<?>> ants,
AntType type) {
return ants.stream()
.filter(ant -> ant.getType() == type)
.map(ant -> (T) ant.self())
.toList();
}
Usage example:
public static void main(String[] args) {
List<Ant<?>> ants = List.of(new AntWarrior(), new AntScout());
// compiles and runs without issues
List<AntWarrior> antWarriors = getAntsByType(ants, AntType.WARRIOR);
System.out.println(antWarriors);
// compiles and runs without issues
List<AntScout> antScouts = getAntsByType(ants, AntType.SCOUT);
System.out.println(antScouts);
}
Output:
[AntWarrior{}]
[AntScout{}]
A link to Online Demo
This could be possible if enums could be generic, but they can't. However, that is no big deal. Just use a final class with a bunch of public static final fields and a private constructor. A little verbose surely, but is as effective as an enum.
Also, your getClass() method should either be a static method with the switch or else be an instance method without the switch. The later is much better, so went that way. Further, calling it getClass() is not a good idea since it is unrelated with Object.getClass() method. So I called it getAntTypeClass().
And this is the result:
public class Main {
public static void main(String[] args) {
System.out.println(AntType.QUEEN.getAntTypeClass().getName());
System.out.println(AntType.SCOUT.getAntTypeClass().getName());
}
}
final class AntType<T extends Ant> {
public static final AntType<AntQueen> QUEEN = new AntType<>(AntQueen.class );
public static final AntType<AntWarrior> WARRIOR = new AntType<>(AntWarrior.class );
public static final AntType<AntGatherer> GATHERER = new AntType<>(AntGatherer.class);
public static final AntType<AntScout> SCOUT = new AntType<>(AntScout.class );
private final Class<T> antTypeClass;
private AntType(Class<T> antTypeClass) {
this.antTypeClass = antTypeClass;
}
public Class<T> getAntTypeClass() {
return antTypeClass;
}
}
interface Ant {}
class AntWarrior implements Ant {}
class AntGatherer implements Ant {}
class AntScout implements Ant {}
class AntQueen implements Ant {}
See it working on ideone.
I would change your AntType enum method so that it acts as the filter in your stream. I've had to guess at the rest of the class hierarchy but this might give you a starting point.
import java.util.List;
import static java.util.stream.Collectors.toList;
public class Demo {
private List<Ant> ants = List.of(
new AntQueen(),
new AntScout(),
new AntGatherer(),
new AntWarrior());
public static void main(String[] args) {
var demo = new Demo();
System.out.println(demo.getAntsType(AntType.QUEEN));
}
public List<Ant> getAntsType(AntType type) {
return ants.stream().filter(type::matches).collect(toList());
}
}
class Ant {}
class AntQueen extends Ant {}
class AntWarrior extends Ant {}
class AntGatherer extends Ant {}
class AntScout extends Ant {}
enum AntType {
QUEEN, WARRIOR, GATHERER, SCOUT;
public boolean matches(Ant a) {
return switch (this) {
case QUEEN -> a instanceof AntQueen;
case WARRIOR -> a instanceof AntWarrior;
case GATHERER -> a instanceof AntGatherer;
case SCOUT -> a instanceof AntScout;
};
}
}
There are a couple ways you can do this.
First, fix the method in your enum:
public enum AntType {
QUEEN,WARRIOR,GATHERER,SCOUT;
public Class<? extends Ant> getImplClass(){
return switch (this) {
case QUEEN -> AntQueen.class;
case WARRIOR -> AntWarrior.class;
case GATHERER -> AntGatherer.class;
case SCOUT -> AntScout.class;
};
}
}
Since this is a non static method, you don't need to take in the type as an argument. In your example it's not clear where the list is coming from, but if I add it as an argument, it would look like this:
public static List<Ant> getAntsType(AntType type, List<Ant> ants){
return ants.stream().filter(ant -> ant.getClass() == type.getImplClass()).toList();
}
The second way to do it would be to add a method called getType() in the Ant class which returns a type variable that is set by the constructor.
public class Ant {
private AntType type;
protected Ant(AntType type) {
this.type = type;
}
public AntType getType() {
return type;
}
}
Then you set the type in each of the subclass's constructors:
public class AntQueen extends Ant {
protected AntQueen() {
super(AntType.QUEEN);
}
}
Then the filtering code looks like this:
public static List<Ant> getAntsType(AntType type, List<Ant> ants){
return ants.stream().filter(ant -> ant.getType() == type).toList();
}

java generics: Bound mismatch for string

my code is as below, and I got the error message Bound Mismatch Error: The type String is not a valid substitute for the bounded parameter <K extends myComparable<K>> of the type myInterface<K,V>:
interface myComparable<T> {
public int compareTo(T o);
}
interface myInterface<K extends myComparable<K>, V> {
}
public class myClass implements myInterface<String,String>{
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
However, if I changed K extends myComparable<K> to K extends Comparable<K> (without changing the first line; i.e. to use Comparable instead of myComparable), the error will be solved.
Why? And how can I use my own myComparable?
I finally got a solution (i.e. to use myString instead of String):
interface myComparable<T> {
public int compareTo(T o);
}
interface myInterface<K extends myComparable<K>, V> {
}
class myString implements myComparable<myString>{
#Override
public int compareTo(myString o) {
return 0;
}
}
public class myClass implements myInterface<myString,myString>{
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
When you write implements myInterface<String, String>, you're 'binding' the K type variable to String and the V type variable to String.
The declaration of the K type variable in particular has a bound on it: You've declared it as myInterface<K extends myComparable<K>, V> which means that any bound you pick for K must at least 'fit' this restriction.
And it doesn't, which is why the compiler won't let you.
The java.lang.String class actually implements Comparable<String> - it's right there in the javadoc as well as the source if you care to look; you can also just cast it:
Comparable<String> test = "hello"; // this compiles and runs fine.
The reason is that string was written by sun/oracle as: public final class String implements Comparable<String>.
It was not written with implements myComparable<String>.
It is not possible to make java.lang.String implement your interface.
That is not how interfaces work; java is nominally and not structurally typed: You can't decree that all Strings are myComparables, just because they so happen to have a compareTo method.
Imagine it worked that way and I wrote this class:
public class Gun {
public void shoot(Person person) { ... }
}
quite a dangerous class!
Let's say it worked the way you appear things are. Then I could do:
public interface Camera {
public void shoot(Person p);
}
Camera c = new Gun();
c.shoot(somebody);
and good grief, now we have an extremely dangerous situation going on. Fortunately, java does not work this way; A Gun is not a Camera. Eventhough it so happens to have all the methods that the Camera interface declared.
You can make your own types that implement your own interfaces, of course. That's no problem. However, in general, it doesn't seem useful to make an interface named myComparable.

Sort ArrayList of objects that are instance of sub classes of abstract class

this my main structure:
Some of the interface methods are implemented in class A, all the rest are implemented in sub classes.
public interface I
{
// some methods
//
}
public abstract class A implements I
{
// some variables and methods
//
}
public class B extends A
{
// some variables and methods
//
}
public class C extends A
{
// some variables and methods
//
}
public abstract class D extends A
{
// some variables and methods
//
}
public class E extends D
{
// some variables and methods
//
}
public class Test
{
public static void main(String[] args)
{
ArrayList<I> la = new ArrayList<I>();
la.add(new B(..));
la.add(new C(..));
la.add(new C(..));
la.add(new B(..));
la.add(new E(..));
}
}
There are constructors in B, C and E classes.
I need to sort la by variable of class A, the variable is int data type.
I try to change to
public abstract class A implements I, Comparable<A>
But I get an error because of missing public int compareTo(A o) method in all nonabstract classes.
What I need to do ?
Thanks.
I solved it by adding
public interface I extends Comparable<I>
and in class A I changed the method compareTo to
public int compareTo(I obj)
{
return someVariable - obj.someVariable;
}
public abstract class A implements I, Comparable<A> {
// some variables and methods
#Override
public int compareTo(A o) {
return someVariable - o.someVariable;
}
}
You don't need no constructor in A to implement a compareTo method, and you have got some variables you may use for comparison. compareTo is just a method, so since you can have methods in A, you can also have a compareTo method. Since I don't know what varables you've got nor the sort order you require, you will have to fill out the method yourself.
On the other hand it could well be a good idea to have a constructor in A, but this is a completely independent question.
Edit: I didn’t think this through at first: you will of course want to do
Collections.sort(la);
This is not as straightforward as it may sound. Collections.sort() is a generic method declared according to the docs as:
static <T extends Comparable<? super T>> void sort(List<T> list)
This means that for the compiler to be happy about a call to the method, the declared element type of the list must be one that implements Comparable<U> for some type U that is either the element type or a supertype of it. Your element type is I, and I doesn’t implement Comparable. This is why you get the error message.
The solution? I don’t think the perfect solution exists. Assuming you don’t want to declare la an ArrayList<A>, another option is to declare that I is comparable:
public interface I extends Comparable<I>
Strictly speaking this is promising more about A than we can fulfil. We can compare two A objects (even when they are instances of subclasses of A), but there might be other implementations of I, and we may not know how to compare them to A. One way out is:
#Override
public int compareTo(I o) {
A oa = (A) o; // will throw ClassCastException if o is not an A
return someVariable - oa.someVariable;
}
Since A extends I and I extends Comparable<I>, we now have to declare o an I, not an A. If somebody gives us some foreign I implementation, we throw a ClassCastException, and the sorting would propagate that to the caller. However, we know that in your list all elements are instances of subclasses of A, so this won’t happen. With the above, both your call to S.sortBySome() and its call to Collections.sort() will work.

Return type from a Java Factory Pattern

This might be a very basic question with a very obvious answer but i am having hard time figuring this out.
How to know the return type of a method of a class involve in java factory patterns. for example looking at the code below... what would be the return type of the method invocation and how to cast it properly... and also how to write the javadoc also for the classes.
i am trying to write a library which user then can plug in to their project...
I have an interface
public interface myInterface
{
public Object doA();
public Object doB();
}
and concrete Classes as follow
public class concerete1 implements myInterface
{
public concerete1() {
}
#override
public Object doA()
{ return new String("Hello"); }
#override
public Object doB()
{ return "hello".getBytes(); }
}
and
public class concerete1 implements myInterface
{
public concerete2() {
}
#override
public Object doA()
{ return "hello".getBytes(); }
#override
public Object doB()
{ return new String("Hello"); }
}
and my factory class is as follow
public class factory
{
private myInterface mi;
public myInterface actionProducer(String choice)
{
switch(choice)
{
case "a":
mi = new concerete1();
break;
case "b":
mi = new concerete2();
break;
}
return mi;
}
}
and my test runner class is as follow
String result = factory.actionProducer("a").doA();
You should not have to explicitly test the dynamic type of a factory method's return value. The static type should tell you all you need to know. That means the return type should be as specific as it needs to be to tell you what you can do with the object. For example, a factory method that makes maps of varying implementation should return Map:
public interface MapFactory {
public Map makeMap();
...
}
Whether the Map is a HashMap or TreeMap or ConcurrentSkipListMap, you can use the Map methods to interact with it. If it turns out you need to call ceilingKey, which isn't a Map method, you have a design problem.
In your case, your factory methods make no sense, since there is no more specific type to return than Object, and nothing you can do with the return values beyond the API of Object. A more reasonable factory would return objects that can be interacted with the same way, regardless of how the objects are implemented.
You shouldn't be interested in real factory product type. Abstract factory are constructed for factoring objects with common interface / abstract superclass.
So, if you will have
public abstract class Animal {
public void eat();
public String foo();
}
and implementor classes:
public class Dog extends Animal {
public void eat() {
//stuff here
}
public String foo() {
return "howgh";
}
}
public class Cat extends Animal {
public void eat() {
//stuff here
}
public String foo() {
return "meow";
}
}
Your factory interface will look something like this:
public interface AnimalFactory {
public Animal createAnimal();
}
And the concrete factory will be
public class CatFactory implements AnimalFactory {
public Cat createAnimal(){
return new Cat();
}
}
public class DogFactory implements AnimalFactory {
public Dog createAnimal(){
return new Dog();
}
}
So you can create common interface products, without knowing their real class:
Animal awesomeAnimal = catFactory.createAnimal();
System.out.println(awesomeAnimal.foo());
the output will be "meow". It is possible, because all products are subclasses of common interface (Animal here).
The return type will be an Object in all cases. I don't know what you're trying to cast to, but if it's a String, casting into a String from a byte array is not possible. You would have to use one of the String class' constructors instead ("String result = new String(factory.actionProducer("a").doA());"). If you were calling "doB()" (and thus getting a String as an Object) you could convert it to a string either by casting it ("String result = (String)factory.actionProducer("a").doA();") or by calling the return Object's toString() method ("String result = factory.actionProducer("a").doB().toString();").
Javadoc for these methods would describe each of them as returning an Object, because that's what they do.
In short, I would change the return types of "doA()" and "doB()" to what they are actually returning (String or byte array), but maybe this is not an option for what you are trying to do. Some additional context might help in coming up with a more detailed answer.
EDIT: Sorry, I didn't realize that the String and byte array return types were reversed over the two implementations. In the answer I described "doA()" as returning a byte array and "doB()" as returning a String, and I believe those are flipped around in the implementation you're using in your example (Concrete1). However, everything else pretty much stands.
The simplest answer would be to declare 'result' as an Object and then force a cast and just hope you got it right: if you don't, you'll get an error at runtime:
Object obj = factory.actionProducer("a").doA();
String str = (String) obj;
However, in your example, doA() returns either String or byte[], depending on the choice of implementation, so this will fail for "b" and succeed for "a". Maybe it was a typo in the question though?
With a slightly clearer definition of your objectives, using generic types might help, but its hard to say without more information.

Method with typed list and inheritance

I have some troubles with a method having a typed List parameter, inherited from another (typed) class.
Let's keep it simple :
public class B<T> {
public void test(List<Integer> i) {
}
}
The B class has a useless generic T, and test() want an Integer List.
Now if I do :
public class A extends B {
// don't compile
#Override
public void test(List<Integer> i) {
}
}
I get a "The method test(List) of type A must override or implement a supertype method" error, that should not happen.
But removing the type of the list works... although it doesn't depend on the class generic.
public class A extends B {
// compile
#Override
public void test(List i) {
And also defining the useless generic below to use the typed list
public class A extends B<String> {
// compile
#Override
public void test(List<Integer> i) {
So I'm clueless, the generic of B should have no influence on the type of the test() list. Does anyone have an idea of what's happening?
Thanks
You're extending the raw type of B, not the generic one. The raw one effectively does not have a test(List<Integer> i) method, but a test(List) method.
If you switch to raw types, all generics are replaced by raws, regardless of whether their type was filled in or not.
To do it properly, do
public class A<T> extends B<T>
This will use the generic type B<T>, which includes the method you want to override.
When you remove use a class without generics (and use it raw), all generics from class methods are forgotten.
Due this reason when you inform the generic type on the second case you get it working.
This:
class T<G> {
public void test(G g);
}
in this case:
class A extends T {
}
will look like this:
class T {
public void test(Object g);
}
This was a java puzzle presented on Google IO 2011 you can see video here

Categories