Java Subclassing Generic Arguments - java

I'm sorry if this question has been asked before, but I don't really know what to search for.
Anyway, I'm making a math package, and many of the classes extend Function:
package CustomMath;
#SuppressWarnings("rawtypes")
public abstract class Function <T extends Function> {
public abstract Function getDerivative();
public abstract String toString();
public abstract Function simplify();
public abstract boolean equals(T comparison);
}
I want to compare functions to see if they're equal. If they're from the same class, I want to use its specific compare method, but if they're of different classes, I want to return false. Here is one of the classes I have currently:
package CustomMath;
public class Product extends Function <Product> {
public Function multiplicand1;
public Function multiplicand2;
public Product(Function multiplicand1, Function multiplicand2)
{
this.multiplicand1 = multiplicand1;
this.multiplicand2 = multiplicand2;
}
public Function getDerivative() {
return new Sum(new Product(multiplicand1, multiplicand2.getDerivative()), new Product(multiplicand2, multiplicand1.getDerivative()));
}
public String toString() {
if(multiplicand1.equals(new RationalLong(-1, 1)))
return String.format("-(%s)", multiplicand2.toString());
return String.format("(%s)*(%s)", multiplicand1.toString(), multiplicand2.toString());
}
public Function simplify() {
multiplicand1 = multiplicand1.simplify();
multiplicand2 = multiplicand2.simplify();
if(multiplicand1.equals(new One()))
return multiplicand2;
if(multiplicand2.equals(new One()))
return multiplicand1;
if(multiplicand1.equals(new Zero()) || multiplicand2.equals(new Zero()))
return new Zero();
if(multiplicand2.equals(new RationalLong(-1, 1))) //if one of the multiplicands is -1, make it first, so that we can print "-" instead of "-1"
{
if(!multiplicand1.equals(new RationalLong(-1, 1))) // if they're both -1, don't bother switching
{
Function temp = multiplicand1;
multiplicand1 = multiplicand2;
multiplicand2 = temp;
}
}
return this;
}
public boolean equals(Product comparison) {
if((multiplicand1.equals(comparison.multiplicand1) && multiplicand2.equals(comparison.multiplicand2)) ||
(multiplicand1.equals(comparison.multiplicand2) && multiplicand2.equals(comparison.multiplicand1)))
return true;
return false;
}
}
How can I do this?

With generic you have the guarantee that the equals method is only apply with the type 'T', in this case 'Product'. You can't passe another class type.
Another possibility would be in classe Function define:
public abstract boolean equals(Function comparison);
And in classe Product the object comparison whith a comparison instanceof Product

Override Object.equals(Object) method. You don't need to use generics here. Its body will look something like this
if (other instanceof Product) {
Product product = (Product) other;
// Do your magic here
}
return false;

Related

check each object, return true when the first condition is met, else return false

I have a method that works fine. This is how it looks.
private ArrayList<Car> carsInStore ; //in car class have setter/getter/quals/Constructor.
public boolean checkIfcarInStore(Car c) {
for (Car car : carsInStore) {
if(car.equals(c)){
return true;
}
}
}
I want to switch this to Lambda.
But I am not sure how fill in the if (condition) return true or return false outside.
And I know I can do it in stream too. Can anyone give an example?
If you really want to use lambda, this should work else you have your answer within your comment.
private ArrayList<Car> carsInStore ;
public boolean checkIfcarInStore(Car c) {
return carsInStore.stream().anyMatch(c::equals);
}
}
You can substitute the method checkIfcarInStore() with a Predicate, which is a functional interface representing a boolean condition, that can be implemented as a lambda expression:
Predicate<Car> isInStore = car -> carsInStore.contains(car);
or as a method reference:
Predicate<Car> isInStore = carsInStore::contains;
If according to the instructions of your assignment you need to have a method checkIfcarInStore(), the predicate can be declared as a field and used internally inside the method:
private ArrayList<Car> carsInStore ;
private Predicate<Car> isInStore = car -> carsInStore.contains(car);
public boolean checkIfCarInStore(Car car) {
return isInStore.test(car);
}

Java imitate and, or for concatenate rule

I have a Java class like below
class MyClass {
public boolean rule1() {...}
public boolean rule2() {...}
public boolean rule3() {...}
}
now for instance I want to check the rule of above class in many ways such as :
MyClass myClass = new MyClass();
if (myClass.rule1() && myClass.rule2 || myClass.rule3) {}
and Now I am wondering that how can I implement above line with like this one?
if (myClass.rule1().and().rule2().or().rule3().accept()) {}
The cleaner way would be to use the functional interface Predicate:
Type Parameters:
T - the type of the input to the predicate Functional
Interface: This is a functional interface and can therefore be used as
the assignment target for a lambda expression or method reference.
public class A {
public Predicate rule1() {
return //some operation that returns a boolean;
}
public Predicate rule2() {
return //some operation that returns a boolean;
}
public Predicate rule3() {
return //some operation that returns a boolean;
}
}
But the if chain of method calls would not look like you are looking for, namely:
if (myClass.rule1().and().rule2().or().rule3().accept()) {}
Otherwise, you would have to implement the Builder pattern, and implement the and(), or(), and accept methods. For instance:
public class BooleanEvaluator {
List<String> rules = new ArrayList<>();
public BooleanEvaluator and() {
rules.add("&&");
return this;
}
public BooleanEvaluator or() {
rules.add("or");
return this;
}
public boolean accept() {
int i = 0;
boolean result = Boolean.parseBoolean(rules.get(0));
while (i < rules.size() - 1) {
if(rules.get(i).equals("&&")){
result = result && Boolean.parseBoolean(rules.get(i + 1));
i+=2;
}
else if(rules.get(i).equals("||")){
result = result || Boolean.parseBoolean(rules.get(i + 1));
i+=2;
}
}
return false;
}
public BooleanEvaluator rule1() {
boolean result = // apply the rule 1
rules.add(String.valueOf(result));
return this;
}
public BooleanEvaluator rule2() {
boolean result = // apply the rule 2
rules.add(String.valueOf(result));
return this;
}
public BooleanEvaluator rule3() {
boolean result = // apply the rule 3
rules.add(String.valueOf(result));
return this;
}
void some_method(){
if (this.rule1().and().rule2().or().rule3().accept()) {
// ...
}
}
}
Naturally, the accept method would have to be much more robust, this is just to show what would the design look like.
Have a look at Predicate<T> and its and or or.
MyClass instance = new MyClass();
Predicate<MyClass> predicate = MyClass::rule1;
if (predicate.and(MyClass::rule2).or(MyClass::rule3).test(instance)) {
// todo
}
It might look less readable than the version you mentioned, renaming MyClass to something more meaningful would help. If it doesn't work for you, consider writing a Builder. Good complex examples of which can be found in, let's say, dynamic SQL builders (for example, jooq).

Overriding generic equals method

To preface this, I've looked for numerous examples prior to asking and can't find any solution in regards to my problem.
I'm trying to implement a generic queue in a program I'm making, but stuck at a certain point. The program I've made is supposed to simulate a printer, queued with print jobs. There is a Queue class, PrintQueue class, and job class. (It is important to note the Job class consists of a job ID and String of who ordered it). I've included a function (in the printQueue class) where if the first job matches the job ID you put in, it will be deleted.
Unfortunately however, the queue is generic. This means I can't traverse the array with just an integer to check equality because it is a queue of job objects. To fix this I create a job with a blank name, and regular ID. The Job class has an equals method, which determines if either ID or Owner match, then it is true. But when I execute the code, this class is not called. The generic equals class is called instead, which will of course be false. After looking at many examples on this site, I tried all the recommended solutions, which did not work for me as my case (and problem) are different. What can I do to override the generic equals method? My code below is as simple as I could make it to reproduce this problem while keep context.
JOB CLASS
public class Job{
private String owner;
private int jobId;
public Job(String o, int j){
owner = o;
jobId = j;
}
public String getOwner(){
return owner;
}
public int getJobId(){
return jobId;
}
public String toString() {
return owner + " " + jobId + ". ";
}
public boolean equals(Job a) {
if(this.jobId == a.getJobId() || this.owner.equals(a.getOwner())) {
return true;
}
else
System.out.println("nomatch");
return false;
}
}
GENERIC QUEUE CLASS
import java.util.ArrayList;
public class Queue<T>{
private ArrayList<T> queue;
public Queue() {
queue = new ArrayList<T>();
}
public void enQueue(T obj1) {
queue.add(obj1);
}
public T deQueue() {
if(queue.size() != 0) {
T temp = queue.get(queue.size() - 1);
queue.remove(queue.size() -1);
return temp;
}
else
return null;
}
public int size() {
return queue.size();
}
public boolean isEmpty() {
if (size() == 0) {
return true;
}
else
return false;
}
public int positionOf(T a) {
for(int x = 0; x < queue.size(); x++) {
if(a.equals(queue.get(x))) {
System.out.println("Positionmatch");
return x;
}
}
return -1;
}
}
PRINTQUEUE CLASS
public class PrintQueue {
Queue<Job> prqueue = new Queue<Job>();
public PrintQueue() {}
public void lprm(int jobID) { //Removes the active job at the front of the queue if jobId matches, error message otherwise
//I can't JUST use jobID to check the position because the queue is a collection of JOBS not JobId's
if (prqueue.positionOf(new Job("",jobID))==0) {
prqueue.deQueue();
}
else if (prqueue.positionOf(new Job("",jobID))== -1) {
System.out.println("Job does not occupy first row.");
}
}
}
I know this is an extensive question, so if you do take the time to read it thank you very much. I wouldn't ask this if I could find the answer anywhere else.
Solution is simple: you are not overriding equals in your class, common mistake. Always annotate your methods with #Override so you can avoid this mistake.
Real equals method is taking an Object parameter, and yours has a Job as parameter, change that to Object and then cast it accordingly.
If you are using IDE I suggest right click -> source -> generate equals and you will see a good example how to do it.
You have to override your methods like this
#Override
public boolean equals(Object a) {
if(!(a instanceof Job))
throw new IllegalArgumentException();
Job job =(Job)a;
if(this.jobId == job.getJobId() || this.owner.equals(job.getOwner())) {
return true;
}
else
System.out.println("nomatch");
return false;
}
See also Why do I need to override the equals and hashCode methods in Java?

java compare to different options

I have implemented compareTo to allow me to compare my class' based on some criteria and it is working fine.
However, at some point I want to compare the class' on one thing and at another point in the code I want to compare the class based on another thing.
Is it possible to have two different implementations of compareTo and using one at some point and one at another?
In general the mechanism to do this is to implement one or more Comparators and use the appropriate one as needed.
Since your Class is "Comparable" you can use the compareTo, you can't - however - create more then one implementation of that function to be used at different points in the same Class (you have one function to override, and you can't do that twice).
You can, however, take a look at the Comparator Interface; and implementation of that interface can allow you to implement and use a different compareTo for your object.
We achieved something similar by writing a utility comparator for our class - something like this:
public class FooComparator implements Comparator<Foo> {
public static String COMPARE_FIELD1 = "COMPARE_FIELD1";
public static String COMPARE_FIELD2 = "COMPARE_FIELD2";
public static String COMPARE_FIELD3 = "COMPARE_FIELD3";
private String compareBy = COMPARE_FIELD1;
private boolean reverse = true;
public FooComparator(){}
public FooComparator(String sort){
compareBy = sort;
}
public void reverse() {
if(reverse) {reverse = false;
} else {reverse = true;}
}
public void field1Sort() {compareBy = COMPARE_FIELD1;}
public void field2Sort() {compareBy = COMPARE_FIELD2;}
public void field3Sort() {compareBy = COMPARE_FIELD3;}
public int compare(Foo foo1, Foo foo2) {
if(compareBy.equals(COMPARE_FIELD2)) {
return compareByField2(foo1, foo2);
} else if(compareBy.equals(COMPARE_FIELD3)) {
return compareByField3(foo1, foo2);
}
return compareByField1(foo1, foo2);
}
private int compareByField1(Foo foo1, Foo foo2) {
if(reverse) {return foo1.getField1().compareTo(foo2.getField1());}
return foo1.getField1().compareTo(foo2.getField1());
}
private int compareByField2(Foo foo1, Foo foo2) {
if(reverse) {return foo1.getField2().compareTo(foo2.getField2());}
return foo1.getField2().compareTo(foo2.getField2());
}
private int compareByField3(Foo foo1, Foo foo2) {
if(reverse) {return foo1.getField3().compareTo(foo2.getField3());}
return foo1.getField3().compareTo(foo2.getField3());
}
}
We then can use it like this:
List<Foo> foos = new ArrayList<Foo>();
FooComparator comparator = new FooComparator(FooComparator.COMPARE_FIELD1);
Collections.sort(foos, comparator);

Java Best Practice for type resolution at runtime

I'm trying to define a class (or set of classes which implement the same interface) that will behave as a loosely typed object (like JavaScript). They can hold any sort of data and operations on them depend on the underlying type.
I have it working in three different ways but none seem ideal. These test versions only allow strings and integers and the only operation is add. Adding integers results in the sum of the integer values, adding strings concatenates the strings and adding an integer to a string converts the integer to a string and concatenates it with the string. The final version will have more types (Doubles, Arrays, JavaScript-like objects where new properties can be added dynamically) and more operations.
Way 1:
public interface DynObject1 {
#Override public String toString();
public DynObject1 add(DynObject1 d);
public DynObject1 addTo(DynInteger1 d);
public DynObject1 addTo(DynString1 d);
}
public class DynInteger1 implements DynObject1 {
private int value;
public DynInteger1(int v) {
value = v;
}
#Override
public String toString() {
return Integer.toString(value);
}
public DynObject1 add(DynObject1 d) {
return d.addTo(this);
}
public DynObject1 addTo(DynInteger1 d) {
return new DynInteger1(d.value + value);
}
public DynObject1 addTo(DynString1 d)
{
return new DynString1(d.toString()+Integer.toString(value));
}
}
...and similar for DynString1
Way 2:
public interface DynObject2 {
#Override public String toString();
public DynObject2 add(DynObject2 d);
}
public class DynInteger2 implements DynObject2 {
private int value;
public DynInteger2(int v) {
value = v;
}
#Override
public String toString() {
return Integer.toString(value);
}
public DynObject2 add(DynObject2 d) {
Class c = d.getClass();
if(c==DynInteger2.class)
{
return new DynInteger2(value + ((DynInteger2)d).value);
}
else
{
return new DynString2(toString() + d.toString());
}
}
}
...and similar for DynString2
Way 3:
public class DynObject3 {
private enum ObjectType {
Integer,
String
};
Object value;
ObjectType type;
public DynObject3(Integer v) {
value = v;
type = ObjectType.Integer;
}
public DynObject3(String v) {
value = v;
type = ObjectType.String;
}
#Override
public String toString() {
return value.toString();
}
public DynObject3 add(DynObject3 d)
{
if(type==ObjectType.Integer && d.type==ObjectType.Integer)
{
return new DynObject3(Integer.valueOf(((Integer)value).intValue()+((Integer)value).intValue()));
}
else
{
return new DynObject3(value.toString()+d.value.toString());
}
}
}
With the if-else logic I could use value.getClass()==Integer.class instead of storing the type but with more types I'd change this to use a switch statement and Java doesn't allow switch to use Classes.
Anyway... My question is what is the best way to go about something thike this?
What you are trying to do is called double dispatch. You want the method called to depend both on the runtime type of the object it's called on, and on the runtime type of its argument.
Java and other C derivatives support single dispatch only, which is why you need a kludge like the visitor pattern you used in option 1. This is the common way of implementing it. I would prefer this method because it uses no reflection. Furthermore, it allows you to keep each case in its own method, without needing a big "switchboard" method to do the dispatching.
I'd choose the second option, with the third, I'd better be using generics so you don't rely on that Enum. And with the first option you could be implementing methods for the rest of your life. Anyways you could use "instanceof" operator for Class matching.

Categories

Resources