Kotlin sealed class - how to sort by sealed class similar to sorting by enum - sorting

In Java we can easily sort a Collecion by enum with something like this:
Collections.sort(toSortEnumList, new Comparator<theEnum>() {
#Override
public int compare(theEnum o1, theEnum o2) {
return o1.ordinal().compareTo(o2.ordinal());
}
});
and the toSortEnumList will be ordered ascending. How can I do this with a Kotlin's sealed classes? I tried sorting by the class names but that's not by enum position. There must be some way to sort by enum position:
sealed class GoodCountries {
class Brazil : GoodCountries() {}
class USA : GoodCountries() {}
class Germany : GoodCountries() {}
class China : GoodCountries() {}
}
// later on
var toSortList = listOf<GoodCountries>(China(), Brazil(), USA(), Germany())
Collections.sort(
toSortList,
{ x: GoodCountries, y: GoodCountries -> y::class.java.name.compareTo(x::class.java.name) }
)
Log.v("myTag", toSortList.toString())
this prints:
USA, Germany, China, Brazil
descending order. Not what I want. I want to sort by sealed class order (like ordinal number in Java's enum) like this:
Brazil, USA, Germany, China
I thought sealed classes are supposed to be better then enums but if I can't do this maybe enums have an advantage.
UPDATE: Thanks to Roland's help I was able to find the list of sealed classes. but now I want to sort by it: here is what I have so far:
Collections.sort(toSortList, object : Comparator<GoodCountries> {
override fun compare(left: GoodCountries, right: GoodCountries): Int {
return Integer.compare(
GoodCountries::class.sealedSubclasses.indexOf(left),
GoodCountries::class.sealedSubclasses.indexOf(right)
)
}
})
but I get the following error at indexOf:
Type inference failed. The value of the type parameter T should be mentioned in input types (argument type, receiver type or expected type). Try to specify it explicitely.

You could give your GoodCountries an order property like so:
sealed class GoodCountries(val order: Int) {
class Brazil : GoodCountries(0)
class USA : GoodCountries(1)
class Germany : GoodCountries(2)
class China : GoodCountries(3)
}
It's not a perfect solution since you have to enumerate by hand, but this way the desired order is guaranteed.
Doing this would simplify your comparison code dramatically:
val sorted = toSortList.sortedBy(GoodCountries::order)
println(sorted.map { it::class.simpleName })
Output:
[Brazil, USA, Germany, China]
Edit: Updated with great idea of Chrispher which made the code even cleaner (having order property in constructor of GoodCountries instead of making it an abstract variable which is overriden by the subclasses).

Maybe not completely what you are looking for, but maybe it is...
While the sealed classes don't seem to have something like an ordinal, which you've already noticed, there is sealedSubclasses on the class itself (i.e. GoodCountries::class.sealedSubclasses). Also, it seems as if the order of the sealedSubclasses is the one of the defined classes, i.e. Brazil in this list always comes first, USA second, etc. The order is different if they aren't all nested (i.e. if some are outside, they are listed first).
However: the documentation doesn't state that this ordering was chosen deliberately. Neither in the 'Sealed classes' reference documentation nor in the sealedSubclasses (k)documentation.
Regarding your question about sorting entities in the sealed class order, you may want to use something like the following:
val entityList = listOf(Germany(), China(), USA(), Brazil(), Germany())
entityList.sortedBy { // or use sortedWith(compareBy {
GoodCountries::class.sealedSubclasses.indexOf(it::class)
}.forEach(::println) // or toList...
or something like:
GoodCountries::class.sealedSubclasses
.asSequence()
.flatMap { klazzInOrder ->
entityList.asSequence().filter { it::class == klazzInOrder }
}
.forEach(::println)
Both might not be the best choices regarding performance, but I think you get the idea.
The sort samples which I added before (when I didn't realize that you actually want to sort entities instead of the types):
println("Listing the sealed classes in the order of their declaration*")
GoodCountries::class.sealedSubclasses.forEach(::println)
println("Listing the sealed classes ordered by their simple name")
GoodCountries::class.sealedSubclasses.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.simpleName!! })
.forEach(::println)
// same result, but written differently
GoodCountries::class.sealedSubclasses.sortedBy { it.simpleName?.toLowerCase() }
.forEach(::println)
You may even want to combine nullsLast and CASE_INSENSITIVE_ORDER (most probably if you are not dealing with sealed classes) in which case you would write something like:
GoodCountries::class.sealedSubclasses.sortedWith(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)) { it.simpleName })
.forEach(::println)

The quick answer to your question is to switch x and y in your comparator, ie x::class.java.name.compareTo(y::class.java.name)
The longer answer is, for your use case, an enum might be better. Sealed classes shine when some subclasses look different than others, and it's meaningful to have multiple instances of them. For example a sealed class Result with subclasses Success and Error, where Success holds data and Error holds an exception. Assuming you want to treat all countries the same, your use case seems like it might be more suited to a traditional enum.

Related

Is there an accepted way to adjust this so that all of my `enum class` elements are grouped together in the ClassView?

Old code:
typedef enum tagUndoAction { UNDO_CHANGE_CELL = 0,
UNDO_CHANGE_SELECTION_START,
UNDO_CHANGE_SELECTION_SUB } UNDO_ACTION_E;
New code:
enum class UndoAction { ChangeCell = 0,
ChangeSelectionStart,
ChangeSelectionSub } ;
In ClassView:
What I liked about the previous approach was that all of the enumerations were listed together in the ClassView. Now they are displayed A - Z fashion with all the classes.
Is there an accepted way to adjust this so that all of my enum class elements are grouped together in the ClassView?
I guess this is down to personal taste but I have settled on a comporomise of several methods:
I have moved some enum class definitions to inside the class that uses it the most.
For others I have moved them into a AppEnums namespace.
This works for me.

Enums support for inheritance

I frequently come across a situation where we create a class that acts on some enumeration, but later we derive and we want to add more values to the enumeration without changing the base class.
I see this question from 2009:
Base enum class inheritance
However, I know there were a number of changes to enum in C++11, 14, 17.
Do any of those changes allow for extension of enums from base class to derived?
class Base
{
enum State {STATE_1, STATE_2, STATE_3};
};
class Derived : public Base
{
enum State {STATE_4};
};
...where we want derived to have an enumeration describing the states it can be in, which are: STATE_1, STATE_2, STATE_3, and STATE_4. We don't really want to change the enumeration in the base class, because other derived classes might not have the ability to be in STATE_4. We don't really want to create a new enumeration either, because we already have one for State in the Base.
Do we still use static const values instead in order to accomplish this 8 years later?
class Base
{
static int STATE_1= 0;
static int STATE_2= 1;
static int STATE_3= 2;
};
class Derived : public Base
{
static int STATE_4= 3;
};
No, C++ does not allow this sort of thing. Base::Color is a completely separate type from Derived::Color, with zero connection to them. This is no different from any other nested types; nested types defined in a base class are not connected to nested types defined in a derived class.
Nor can enumerations be inherited from one another.
This sort of things tends to go against good OOP practices anyway. After all, if a derived class introduces a new enumerator, how would the base class handle it? How would different derived class instances handle it?
If Base defines an operation over an enumeration, then Base defines the totality of the enumeration it operates on, and every class derived from it ought to be able to handle all of those options. Otherwise, something is very wrong with your virtual interface.
Why not just using namespaces to group enums?
namespace my_codes {
enum class color { red, green, blue } ;
enum class origin { server, client } ;
} // my_codes
Usage might be
struct my_signal {
my_codes::color flag ;
my_codes::origin source ;
} ;
But beware: "overkill is my biggest fear..." :) I would not enjoy some deep hierarchy of namespaces with enums in them and a such ...

Avoiding duplicate code when performing operation on different object properties

I have recently run into a problem which has had me thinking in circles. Assume that I have an object of type O with properties O.A and O.B. Also assume that I have a collection of instances of type O, where O.A and O.B are defined for each instance.
Now assume that I need to perform some operation (like sorting) on a collection of O instances using either O.A or O.B, but not both at any given time. My original solution is as follows.
Example -- just for demonstration, not production code:
public class O {
int A;
int B;
}
public static class Utils {
public static void SortByA (O[] collection) {
// Sort the objects in the collection using O.A as the key. Note: this is custom sorting logic, so it is not simply a one-line call to a built-in sort method.
}
public static void SortByB (O[] collection) {
// Sort the objects in the collection using O.B as the key. Same logic as above.
}
}
What I would love to do is this...
public static void SortAgnostic (O[] collection, FieldRepresentation x /* some non-bool, non-int variable representing whether to chose O.A or O.B as the sorting key */) {
// Sort by whatever "x" represents...
}
... but creating a new, highly-specific type that I will have to maintain just to avoid duplicating a few lines of code seems unnecessary to me. Perhaps I am incorrect on that (and I am sure someone will correct me if that statement is wrong :D), but that is my current thought nonetheless.
Question: What is the best way to implement this method? The logic that I have to implement is difficult to break down into smaller methods, as it is already fairly optimized. At the root of the issue is the fact that I need to perform the same operation using different properties of an object. I would like to stay away from using codes/flags/etc. in the method signature if possible so that the solution can be as robust as possible.
Note: When answering this question, please approach it from an algorithmic point of view. I am aware that some language-specific features may be suitable alternatives, but I have encountered this problem before and would like to understand it from a relatively language-agnostic viewpoint. Also, please do not constrain responses to sorting solutions only, as I have only chosen it as an example. The real question is how to avoid code duplication when performing an identical operation on two different properties of an object.
"The real question is how to avoid code duplication when performing an identical operation on two different properties of an object."
This is a very good question as this situation arises all the time. I think, one of the best ways to deal with this situation is to use the following pattern.
public class O {
int A;
int B;
}
public doOperationX1() {
doOperationX(something to indicate which property to use);
}
public doOperationX2() {
doOperationX(something to indicate which property to use);
}
private doOperationX(input ) {
// actual work is done here
}
In this pattern, the actual implementation is performed in a private method, which is called by public methods, with some extra information. For example, in this case, it can be
doOperationX(A), or doOperationX(B), or something like that.
My Reasoning: In my opinion this pattern is optimal as it achieves two main requirements:
It keeps the public interface descriptive and clear, as it keeps operations separate, and avoids flags etc that you also mentioned in your post. This is good for the client.
From the implementation perspective, it prevents duplication, as it is in one place. This is good for the development.
A simple way to approach this I think is to internalize the behavior of choosing the sort field to the class O itself. This way the solution can be language-agnostic.
The implementation in Java could be using an Abstract class for O, where the purpose of the abstract method getSortField() would be to return the field to sort by. All that the invocation logic would need to do is to implement the abstract method to return the desired field.
O o = new O() {
public int getSortField() {
return A;
}
};
The problem might be reduced to obtaining the value of the specified field from the given object so it can be use for sorting purposes, or,
TField getValue(TEntity entity, string fieldName)
{
// Return value of field "A" from entity,
// implementation depends on language of choice, possibly with
// some sort of reflection support
}
This method can be used to substitute comparisons within the sorting algorithm,
if (getValue(o[i], "A")) > getValue(o[j], "A"))
{
swap(i, j);
}
The field name can then be parametrized, as,
public static void SortAgnostic (O[] collection, string fieldName)
{
if (getValue(collection[i], fieldName)) > getValue(collection[j], fieldName))
{
swap(i, j);
}
...
}
which you can use like SortAgnostic(collection, "A").
Some languages allow you to express the field in a more elegant way,
public static void SortAgnostic (O[] collection, Expression fieldExpression)
{
if (getValue(collection[i], fieldExpression)) >
getValue(collection[j], fieldExpression))
{
swap(i, j);
}
...
}
which you can use like SortAgnostic(collection, entity => entity.A).
And yet another option can be passing a pointer to a function which will return the value of the field needed,
public static void SortAgnostic (O[] collection, Function getValue)
{
if (getValue(collection[i])) > getValue(collection[j]))
{
swap(i, j);
}
...
}
which given a function,
TField getValueOfA(TEntity entity)
{
return entity.A;
}
and passing it like SortAgnostic(collection, getValueOfA).
"... but creating a new, highly-specific type that I will have to maintain just to avoid duplicating a few lines of code seems unnecessary to me"
That is why you should use available tools like frameworks or other typo of code libraries that provide you requested solution.
When some mechanism is common that mean it can be moved to higher level of abstraction. When you can not find proper solution try to create own one. Think about the result of operation as not part of class functionality. The sorting is only a feature, that why it should not be part of your class from the beginning. Try to keep class as simple as possible.
Do not worry premature about the sense of having something small just because it is small. Focus on the final usage of it. If you use very often one type of sorting just create a definition of it to reuse it. You do not have to necessary create a utill class and then call it. Sometimes the base functionality enclosed in utill class is fair enough.
I assume that you use Java:
In your case the wheal was already implemented in person of Collection#sort(List, Comparator).
To full fill it you could create a Enum type that implement Comparator interface with predefined sorting types.

Gson, How to write a JsonDeserializer for Generic Typed Classes?

Situation
I have a class that holds a generic type, and it also has a non-zero arg constructor. I don't want to expose a zero arg constructor because it can lead to erroneous data.
public class Geometries<T extends AbstractGeometry>{
private final GeometryType geometryType;
private Collection<T> geometries;
public Geometries(Class<T> classOfT) {
this.geometryType = lookup(classOfT);//strict typing.
}
}
There are several (known and final) classes that may extend AbstractGeometry.
public final Point extends AbstractGeometry{ ....}
public final Polygon extends AbstractGeometry{ ....}
Example json:
{
"geometryType" : "point",
"geometries" : [
{ ...contents differ... hence AbstractGeometry},
{ ...contents differ... hence AbstractGeometry},
{ ...contents differ... hence AbstractGeometry}
]
}
Question
How can I write a JsonDeserializer that will deserialize a Generic Typed class (such as Geometires)?
CHEERS :)
p.s. I don't believe I need a JsonSerializer, this should work out of the box :)
Note: This answer was based on the first version of the question. The edits and subsequent question(s) change things.
p.s. I don't believe I need a JsonSerializer, this should work out of the box :)
That's not the case at all. The JSON example you posted does not match the Java class structure you apparently want to bind to and generate.
If you want JSON like that from Java like that, you'll definitely need custom serialization processing.
The JSON structure is
an object with two elements
element 1 is a string named "geometryType"
element 2 is an object named "geometries", with differing elements based on type
The Java structure is
an object with two fields
field 1, named "geometryType", is a complex type GeometryType
field 2, named "geometries" is a Collection of AbstractGeometry objects
Major Differences:
JSON string does not match Java type GeometryType
JSON object does not match Java type Collection
Given this Java structure, a matching JSON structure would be
an object with two elements
element 1, named "geometryType", is a complex object, with elements matching the fields in GeometryType
element 2, named "geometries", is a collection of objects, where the elements of the different objects in the collection differ based on specific AbstractGeometry types
Are you sure that what you posted is really what you intended? I'm guessing that either or both of the structures should be changed.
Regarding any question on polymorphic deserialization, please note that the issue was discussed a few times on StackOverflow.com already. I posted a link to four different such questions and answers (some with code examples) at Can I instantiate a superclass and have a particular subclass be instantiated based on the parameters supplied.

Why isn't .Except (LINQ) comparing things properly? (using IEquatable)

I have two collections of my own reference-type objects that I wrote my own IEquatable.Equals method for, and I want to be able to use LINQ methods on them.
So,
List<CandyType> candy = dataSource.GetListOfCandy();
List<CandyType> lollyPops = dataSource.GetListOfLollyPops();
var candyOtherThanLollyPops = candy.Except( lollyPops );
According to the documentation of .Except, not passing an IEqualityComparer should result in EqualityComparer.Default being used to compare objects. And the documentation for the Default comparer is this:
"The Default property checks whether type T implements the System.IEquatable generic interface and if so returns an EqualityComparer that uses that implementation. Otherwise it returns an EqualityComparer that uses the overrides of Object.Equals and Object.GetHashCode provided by T."
So, because I implement IEquatable for my object, it should use that and work. But, it doesn't. It doesn't work until I override GetHashCode. In fact, if I set a break point, my IEquatable.Equals method never gets executed. This makes me think that it's going with plan B according to its documentation. I understand that overriding GetHashCode is a good idea, anyway, and I can get this working, but I am upset that it is behaving in a way that isn't in line with what its own documentation stated.
Why isn't it doing what it said it would? Thank you.
After investigation, it turns out things aren't quite as bad as I thought. Basically, when everything is implemented properly (GetHashCode, etc.) the documentation is correct, and the behavior is correct. But, if you try to do something like implement IEquatable all by itself, then your Equals method will never get called (this seems to be due to GetHashCode not being implemented properly). So, while the documentation is technically wrong, it's only wrong in a fringe situation that you'd never ever want to do (if this investigation has taught me anything, it's that IEquatable is part of a whole set of methods you should implement atomically (by convention, not by rule, unfortunately)).
Good sources on this are:
Is there a complete IEquatable implementation reference?
MSDN Documentation: IEquatable<T>.Equals(T) Method
SYSK 158: IComparable<T> vs. IEquatable<T>
The interface IEqualityComparer<T> has these two methods:
bool Equals(T x, T y);
int GetHashCode(T obj);
A good implementation of this interface would thus implement both. The Linq extension method Except relies on the hash code in order to use a dictionary or set lookup internally to figure out which objects to skip, and thus requires that proper GetHashCode implementation.
Unfortunately, when you use EqualityComparer<T>.Default, that class does not provide a good GetHashCode implementation by itself, and relies on the object in question, the type T, to provide that part, when it detects that the object implements IEquatable<T>.
The problem here is that IEquatable<T> does not in fact declare GetHashCode so it's much easier to forget to implement that method properly, contrasted with the Equals method that it does declare.
So you have two choices:
Provide a proper IEqualityComparer<T> implementation that implements both Equals and GetHashCode
Make sure that in addition to implementing IEquatable<T> on your object, implement a proper GetHashCode as well
Hazarding a guess, are these different classes? I think by default IEquatable only works with the same class. So it might by falling back to the Object.Equal method.
I wrote a GenericEqualityComparer to be used on the fly for these types of methods: Distinct, Except, Intersect, etc.
Use as follows:
var results = list1.Except(list2, new GenericEqualityComparer<MYTYPE>((a, b) => a.Id == b.Id // OR SOME OTHER COMPARISON RESOLVING TO BOOLEAN));
Here's the class:
public class GenericEqualityComparer<T> : EqualityComparer<T>
{
public Func<T, int> HashCodeFunc { get; set; }
public Func<T, T, Boolean> EqualityFunc { get; set; }
public GenericEqualityComparer(Func<T, T, Boolean> equalityFunc)
{
EqualityFunc = equalityFunc;
HashCodeFunc = null;
}
public GenericEqualityComparer(Func<T, T, Boolean> equalityFunc, Func<T, int> hashCodeFunc) : this(equalityFunc)
{
HashCodeFunc = hashCodeFunc;
}
public override bool Equals(T x, T y)
{
return EqualityFunc(x, y);
}
public override int GetHashCode(T obj)
{
if (HashCodeFunc == null)
{
return 1;
}
else
{
return HashCodeFunc(obj);
}
}
}
I ran into this same problem, and debugging led me to a different answer than most. Most people point out that GetHashCode() must be implemented.
However, in my case - which was LINQ's SequenceEqual() - GetHashCode() was never called. And, despite the fact that every object involved was typed to a specific type T, the underlying problem was that SequenceEqual() called T.Equals(object other), which I had forgotten to implement, rather than calling the expected T.Equals(T other).

Resources