I am implementing equals method for a class, which has a member of a Functional Interface type. I do not have a separate class for the concrete implementation of the interface, and I use lambda expression to create and set the interface variable. I want the equals method of the class to take into consideration, the code, which was provided via lambda expression. Different implementations must must not return equal. Is there a way to achieve this properly? Since I did not find any links related to this requirement I am doubting whether such a practice is recommended, even if it is possible to achieve the same. What is the best thing to do?
Related
Beginning with Java SE 8, if the formal parameter of a method is a functional interface, the argument can be either an object implementing that interface or a reference to some method. It means that the argument can also be a reference to a method that is not logically related to the interface's purpose. Is it possible to force the argument to be only an object implementing the interface, but not to be a method reference? Although it is possible to make the interface non-functional by adding a second abstract method, that additional method nevertheless should be implemented. Is there another way?
Is it possible to force the argument to be only an object implementing the interface, but not to be a method reference?
There is not.
Although it is possible to make the interface non-functional by adding a second abstract method, that additional method nevertheless should be implemented. Is there another way?
Indeed, that's the downside of doing that. You can't provide a default implementation, as an interface that has exactly 1 non-defaulted method is considered a FunctionalInterface, and you can't decree it to be not so.
What you can do, however, is turn that interface into an abstract class, which aren't eligible for being supplied in lambda/methodref form.
More generally, don't fight java features. If someone uses a method ref, they know what they are doing. Or they don't, but if they are just stumbling about without a clue, trust me, you can't stop an idiot from ruining a code base by designing good APIs and adding every linter rule you manage to scrounge together. Idiots are far too inventive to be stopped by mere mortals.
Why does the Collection interface have equals(Object o) and hashCode(), given that any implementation will have those by default (inherited from Object) ?
From the Collection JavaDoc:
While
the Collection interface adds no stipulations to the general contract
for the Object.equals, programmers who implement the Collection
interface "directly" (in other words, create a class that is a
Collection but is not a Set or a List) must exercise care if they
choose to override the Object.equals. It is not necessary to do so,
and the simplest course of action is to rely on Object's
implementation, but the implementor may wish to implement a "value
comparison" in place of the default "reference comparison." (The List
and Set interfaces mandate such value comparisons.)
The general contract for the Object.equals method states that equals
must be symmetric (in other words, a.equals(b) if and only if
b.equals(a)). The contracts for List.equals and Set.equals state that
lists are only equal to other lists, and sets to other sets. Thus, a
custom equals method for a collection class that implements neither
the List nor Set interface must return false when this collection is
compared to any list or set. (By the same logic, it is not possible to
write a class that correctly implements both the Set and List
interfaces.)
and
While the Collection interface adds no stipulations to the general contract for the Object.hashCode method, programmers should take note that any class that overrides the Object.equals method must also override the Object.hashCode method in order to satisfy the general contract for the Object.hashCode method. In particular, c1.equals(c2) implies that c1.hashCode()==c2.hashCode().
To answer your specific question: why does it have these methods? It's done simply for convenience to be able to include Java Docs giving hints as to what implementers should do with these methods (e.g. comparing equality of values rather than references).
To add to the other great answers. In the Collections interface, the equals method is defined in that interface to make some decisions in the way equaling two instances of collection should work. From the JAVA 8 documentation:
More generally, implementations of the various Collections Framework
interfaces are free to take advantage of the specified behavior of
underlying Object methods wherever the implementor deems it
appropriate.
So you don’t add methods from the Object class for any other reason that giving more definitiveness to the java doc. This is the reason why you don’t count those methods in the abstract methods in the abstract methods of an interface.
Moreover, in JAVA 8, along the same line of reasoning, default methods from the Object class are not allowed and will generate a compile error. I believe it’s was done to prevent this type of confusion. So if you try to create a default method called hashCode(), for example, it will not compile.
Here is a more in-depth explanation for this behavior in JAVA 8 from the Lambda FAQ:
An interface cannot provide a default implementation for any of the
methods of the Object class. This is a consequence of the “class wins”
rule for method resolution: a method found on the superclass chain
always takes precedence over any default methods that appear in any
superinterface. In particular, this means one cannot provide a default
implementation for equals, hashCode, or toString from within an
interface.
This seems odd at first, given that some interfaces actually define
their equals behavior in documentation. The List interface is an
example. So, why not allow this?
One reason is that it would become more difficult to reason about when
a default method is invoked. The current rules are simple: if a class
implements a method, that always wins over a default implementation.
Since all instances of interfaces are subclasses of Object, all
instances of interfaces have non-default implementations of equals,
hashCode, and toString already. Therefore, a default version of these
on an interface is always useless, and it may as well not compile.
Another reason is that providing default implementations of these
methods in an interface is most likely misguided. These methods
perform computations over the object’s state, but the interface, in
general, has no access to state; only the implementing class has
access to this state. Therefore, the class itself should provide the
implementations, and default methods are unlikely to be useful.
Just to add to the great answers above, it makes sense to have the 'equals' or `hashCode' methods in this scenario:
Collection<Whatever> list1 = getArrayList();
Collection<Whatever> list2 = getAnotherArrayList();
if(list1.equals(list2)){
// do something
}
In the absence of the equals method in the interface, we'll be forced to use concrete types, which is generally not a good practice :
ArrayList<Whatever> list1 = getArrayList();
ArrayList<Whatever> list2 = getAnotherArrayList();
if(list1.equals(list2)){
// do something
}
I am creating a mod for the game Minecraft, which has an interface to implement in-game commands. I need the mod to implement that interface, but override one of its methods with a non-compatible method (different return type). But I need to prevent a situation where other classes that implement that interface will not work or not be recognized by the game.
I think this would require overriding the interface with a new interface that is the same as the original, but with an overloaded version of that method to support the mod's needs. Is this possible (or is there another way I can accomplish this?)
One way to think about interfaces is as a contract.
Implementing classes must strictly adhere to this contract.
This means that the method signatures (including return values and parameter) must match exactly.
The entire point of interfaces is to define the interaction without strictly knowing the implementation.
If the interaction you are looking to implement is different then it's possible that you are trying to use something in a way it wasn't intended for.
Even if it is possible to subclass an interface, it's going to quickly get messy.
It's probably in you best interest to create a new interface (with all the other methods the same).
Since it's not going to be comparable with classes that use interface A, you are saving yourself trouble by separating it entirely.
The interfaces supplied by Mojang/forge team are intended for use within the mojang/forge code. They expect the result types to be returned that the interfaces return. If they don't get that as defined by the contract/interface the code will crash/not compile.
It seems as if you are trying to use an interface for a particular purpose for an own project/api.
Consider writing a new interface specifically for the purpose you intend to use it for. Don't modify core interfaces.
A class can inherit multiple interfaces, so that's not an issue. You can implement AND the forge/mojang interface AND your own.
You can implement the mod class. Then override the method. Also write another method which will overload the method in your implemented class. That way you won't have to change the interface.
I understand what interfaces and abstract classes are, but I don't know how to get the following functionality; if it's possible, that is. I have a bunch of classes which are each going to have a validate() method. Each method may take different parameters. For example, we could have classes with the following methods:
boolean validate();
boolean validate(Block[]);
boolean validate(BlockSet[]);
...
So, basically I want to know if I can use an interface or abstract class, or something else, to define a contract to have a method with a given name and return type implemented, but no restrictions on the set of parameters. Thanks in advance.
You can do this with validate(Object... args), but it's worth questioning whether you really want to. Interfaces and Abstract Classes are useful so that you can group a bunch of similar objects together, and have implementations do different things with the same operation. It seems to me that you wouldn't be able to call this method without knowing what the underlying implementation is, and therefore there is no reason to abstract them.
Try using varargs in an interface:
boolean validate(Object... args) or
'boolean validate(Block... blocks)`
if the Blocks are always a collection, use their supertype:
boolean validate(Collection<Block> blocks)
But then you may need to use some casts. Not best option.
If you want method to take any number pf parameters then you can use Varargs but if you want it to change Type also then its not feasible.
Also what you want to achieve is find a separate way of method overloading, but for that you will have to explicitly specify the methods.
In this post I suggested a solution that uses interface and anonymous class. However, there is one thing to be implemented: the hashCode and equals method.
However I found it is hard to implement equals for anonymous class that implements an interface. In that example the interface is Pair<L,R>, and a factory method Pairs.makePair will return an anonymous implementation for it. Suppose I added an equals implementation. The user may implement their own Pair<L,R> classes with a different equals code, therefore the call userobj.equals(makepairobj) will enter their code, and makepairobj.equals(userobj) will enter my code. Because I have no control of their code, it is hard to make sure equals to be symmetric, which is required for a good implementation.
I believe this problem is common for other cases, so I would like to know how this issue being address generally?
EDIT:
In typical class, the implementation of equals will check the parameter type to make sure it is the same as its own. This guarantee only the implementing code will be called to compare the objects. However, the anonymous class do not have a name and cannot check the type with instanceof. What I can do is make sure it is an instance of the implementing interface/class. Which is not enough to prevent the above scenario.
You can use this.getClass() (with either == or isAssignableFrom()) to compare the types.
Edit
As in:
public boolean equals(Object obj) {
if (getClass() == obj.getClass()) {
// do whatever
}
return false;
}
Usually, when you make an interface like this, it requires the implementing classes to implement equals and hashCode to follow some convention. For example, if you look at the java.util.List interface, it requires lists to be equal iff they have the same length and equal elements in the same order, and it specifies a formula for calculating the hashCode based on the hash codes of the elements.
So then "it is hard to make sure equals to be symmetric" should not be a problem.
The problem you've encountered is a sign that an anonymous class is the wrong way to implement this.
Anonymous classes are a simply a shorthand way of implementing an interface or extending a class. It's purely syntactic sugar, with no extra functionality or other advantage. They were (perhaps mistakenly) intended to make your code simpler and more readable. If an anonymous class complicates your code instead, don't use it.
Many cases that used to be a good fit for anonymous classes are now better served by lambdas. If a class has two or three methods, trying to put it in an anonymous class makes your code hard to read; it should be an inner class anyway.