{"action":"created","issue":{"url":"https://api.github.com/repos/jMetal/jMetal/issues/68","labels_url":"https://api.github.com/repos/jMetal/jMetal/issues/68/labels{/name}","comments_url":"https://api.github.com/repos/jMetal/jMetal/issues/68/comments","events_url":"https://api.github.com/repos/jMetal/jMetal/issues/68/events","html_url":"https://github.com/jMetal/jMetal/pull/68","id":78248700,"number":68,"title":"Generics on quality indicators","user":{"login":"matthieu-vergne","id":1774210,"avatar_url":"https://avatars.githubusercontent.com/u/1774210?v=3","gravatar_id":"","url":"https://api.github.com/users/matthieu-vergne","html_url":"https://github.com/matthieu-vergne","followers_url":"https://api.github.com/users/matthieu-vergne/followers","following_url":"https://api.github.com/users/matthieu-vergne/following{/other_user}","gists_url":"https://api.github.com/users/matthieu-vergne/gists{/gist_id}","starred_url":"https://api.github.com/users/matthieu-vergne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matthieu-vergne/subscriptions","organizations_url":"https://api.github.com/users/matthieu-vergne/orgs","repos_url":"https://api.github.com/users/matthieu-vergne/repos","events_url":"https://api.github.com/users/matthieu-vergne/events{/privacy}","received_events_url":"https://api.github.com/users/matthieu-vergne/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2015-05-19T21:00:02Z","updated_at":"2015-05-21T12:54:20Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/jMetal/jMetal/pulls/68","html_url":"https://github.com/jMetal/jMetal/pull/68","diff_url":"https://github.com/jMetal/jMetal/pull/68.diff","patch_url":"https://github.com/jMetal/jMetal/pull/68.patch"},"body":"I think that you know there is a lot, lot, lot of work to do regarding the generics, because you let almost all of them empty thus they don't provide anything else than warnings. I have started revising them and I plan to go ahead with that, because we cannot say in the paper that we use generics to have a better control at compilation if it is to use them in such a way that they are useless. So here is an example of refinement and it would be nice that you do it with some others in order to build some habits. Otherwise you will just add warnings after warnings with useless empty generics.\r\n\r\nHere is this one:\r\n```\r\npublic interface QualityIndicator extends Serializable, DescribedEntity {\r\n  public double execute(Front frontA, Front frontB) ;\r\n  public double execute(List<? extends Solution> frontA, List<? extends Solution> frontB) ;\r\n  public String getName() ;\r\n}\r\n```\r\nFirst of all, 2 warnings tell you that you did not specify the parameters for `Solution` in the second method (1 warning per front).\r\n\r\nHere, my assumption is that you don't care about which kind of `Solution` it is, because this interface is not intended to deal with specific types of data. And here is how it is translated:\r\n```\r\n  public double execute(List<? extends Solution<?>> frontA, List<? extends Solution<?>> frontB) ;\r\n```\r\nThe question mark should be used when you **do not care** about the type (not when you don't know). Otherwise, it should be specified with a proper type or a parameter. When you do not specify any parameter by letting `Solution` alone, it is interpreted as `Solution<?>`. And now we will see why it is a problem.\r\n\r\nSo, what does that mean? It means that you can do all of that:\r\n**SAME SOLUTION CLASS**\r\n```\r\nList<MySolution> frontA = ...;\r\nList<MySolution> frontB = ...;\r\nexecute(frontA, frontB);\r\n```\r\nwhere `MySolution` is for instance a `Solution<String>`, but also:\r\n**SAME SOLUTION PARAMETER**\r\n```\r\nList<Solution<Integer>> frontA = ...;\r\nList<Solution<Integer>> frontB = ...;\r\nexecute(frontA, frontB);\r\n```\r\nas well as, by extension:\r\n**SIMILAR SOLUTION CLASS**\r\n```\r\nList<MySolution1> frontA = ...;\r\nList<MySolution2> frontB = ...;\r\nexecute(frontA, frontB);\r\n```\r\nwhere `MySolution1` and `MySolution2` are two different `Solution<Integer>`, but also:\r\n**DIFFERENT SOLUTION PARAMETER**\r\n```\r\nList<Solution<Integer>> frontA = ...;\r\nList<Solution<Double>> frontB = ...;\r\nexecute(frontA, frontB);\r\n```\r\nand so of course:\r\n**DIFFERENT SOLUTION CLASS**\r\n```\r\nList<MySolution1> frontA = ...;\r\nList<MySolution3> frontB = ...;\r\nexecute(frontA, frontB);\r\n```\r\nwhere `MySolution1 extends Solution<Integer>` and `MySolution3 extends Solution<Double>`\r\n\r\nNow, I assume that you were not expecting the two last cases (maybe three), because you want to have two compatible fronts. If it is not the case, you can close this pull request, because I took the additional assumption that they should be compatible, but please read the remaining to know how a given interpretation is translated into generics.\r\n\r\nIf you want to forbid the two last cases, then you probably want to have the same parameters, and this come with this definition:\r\n```\r\n  public <T> double execute(List<? extends Solution<T>> frontA, List<? extends Solution<T>> frontB) ;\r\n```\r\nThus, you are telling that there is a given type `T` which is common to both `Solutions`. In such a case, what you forbid are the cases where solutions are *fundamentally* different. `MySolution1` and `MySolution2` can still be used together, because they both extends `Solution<Integer>`, thus they are still similar.\r\n\r\nNow let assume that you expect this `execute()` method to be used on solutions coming from the same algorithm, thus they should be as similar as possible (regarding their class, of course, not their data). Thus, you don't want similar solution classes like `MySolution1` and `MySolution2` to be used together. If you reject this assumption, you can close this pull request too, because I take it.\r\n\r\nIf you want to restrict to equivalent classes, then you should not say that only the parameters of the solutions are the same, but that the solutions themselves are the same, so you should also factor the part `? extends Solution`, not just the solution parameter:\r\n```\r\npublic <T, S extends Solution<T>> double execute(List<S> frontA, List<S> frontB) ;\r\n```\r\nHere we factor the definition by creating `S`, and both lists use it, thus they deal with exactly the same type, so you don't allow anymore to use `MySolution1` and `MySolution2` even if they extend the same `Solution<Integer>`. Now you could say that this case should not hold anymore:\r\n```\r\nList<Solution<Integer>> frontA = ...;\r\nList<Solution<Integer>> frontB = ...;\r\nexecute(frontA, frontB);\r\n```\r\nBecause it is the same thing. But no, it is not: `MySolution1` and `MySolution2` are *specializations* of `Solution<Integer>`. So what happen concretely? Java takes the most restrictive types and assess their strict equivalence. Here, `MySolution1` is not `MySolution2` so it does not accept it. If you try it with a parent class and a child class, same thing. However, for the case where you provide two `Solution<Integer>`, then the most restrictive it can find is precisely this level. It cannot go further. And at this level, we can only assess the equivalence, thus it accepts it. Notice that you cannot cast the arguments to `List<Solution<Integer>>` in order to make it works, because the casting is effective on the root type (`List`), not on its parameters.\r\n\r\nNow, if we look closer the definition:\r\n```\r\npublic <T, S extends Solution<T>> double execute(List<S> frontA, List<S> frontB) ;\r\n```\r\nHere, it happens that the parameter of the solution `T` is used only once in `S extends Solution<T>`, thus it does not make any sense anymore to have it and we can rewrite it that way:\r\n```\r\npublic <S extends Solution<?>> double execute(List<S> frontA, List<S> frontB) ;\r\n```\r\nWe are still defining a single `S` which should be used for both lists, but we don't care about the solution parameter. You can add all the parameters you want, but at the end you can replace all the ones which are used only once by `?` and remove their definition, because what generics allow is to describe type equivalences. So if you use it once, no equivalence (which requires at least two elements) is described, so you can remove it.\r\n\r\nThis is the version I have used in this commit, and I have adapted the implementation correspondingly. If it is not what you want, feel free to close without merging, but please consider to fill your parameters in the future, otherwise you will just add work for revision, because not filling the generic parameters is like not using parameters at all.\r\n\r\nFinally, maybe you noticed that we defined the generics at the level of the method itself, not at the class level (e.g. `QualityIndicator<S extends Solution<?>>`). When you introduce generics, it is better to start from the method. One need to declare a generic at the class level is when you want to have equivalences among different methods of the class. Thus, if you have two methods which should deal with the same type of data, then you will define their generic at the class level instead of the method level, because each method definition is independent. This also implies that it cannot change: by defining it at the method level, the concrete type used is determined at the call of the method. Calling the same method from the same instance with different data is possible, as long as they satisfy the constraints when we call the method. By having the generic at the class level, you fix it when you instantiate the instance, thus any call to the method will deal only with the type specified at the instanciation. This is the second case where you can be interested in defining a generic at the class level: when a given instance should always deal with the same type of data, and not adapt at each call."},"comment":{"url":"https://api.github.com/repos/jMetal/jMetal/issues/comments/104260713","html_url":"https://github.com/jMetal/jMetal/pull/68#issuecomment-104260713","issue_url":"https://api.github.com/repos/jMetal/jMetal/issues/68","id":104260713,"user":{"login":"matthieu-vergne","id":1774210,"avatar_url":"https://avatars.githubusercontent.com/u/1774210?v=3","gravatar_id":"","url":"https://api.github.com/users/matthieu-vergne","html_url":"https://github.com/matthieu-vergne","followers_url":"https://api.github.com/users/matthieu-vergne/followers","following_url":"https://api.github.com/users/matthieu-vergne/following{/other_user}","gists_url":"https://api.github.com/users/matthieu-vergne/gists{/gist_id}","starred_url":"https://api.github.com/users/matthieu-vergne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matthieu-vergne/subscriptions","organizations_url":"https://api.github.com/users/matthieu-vergne/orgs","repos_url":"https://api.github.com/users/matthieu-vergne/repos","events_url":"https://api.github.com/users/matthieu-vergne/events{/privacy}","received_events_url":"https://api.github.com/users/matthieu-vergne/received_events","type":"User","site_admin":false},"created_at":"2015-05-21T12:54:20Z","updated_at":"2015-05-21T12:54:20Z","body":"For the set coverage, I don't see why you qualify it as a quality indicator if none of the two fronts is a reference. One does not need to be a true front to be a reference, if it is for instance the best you know it is fine to. The point is that the reference does not have the same consideration than the evaluated one. If they are both at the \"same level\", then whether you are actually making a *comparator*, whether you are computing something else than some quality evaluations.\r\n\r\nCould you clarify your use of this set coverage and other similar indicators you have?"}}