{"action":"created","issue":{"url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/369","labels_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/369/labels{/name}","comments_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/369/comments","events_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/369/events","html_url":"https://github.com/SpongePowered/SpongeAPI/issues/369","id":53350656,"number":369,"title":"Replace Optional<X> with Optional<? extends X>","user":{"login":"ST-DDT","id":1579362,"avatar_url":"https://avatars.githubusercontent.com/u/1579362?v=3","gravatar_id":"","url":"https://api.github.com/users/ST-DDT","html_url":"https://github.com/ST-DDT","followers_url":"https://api.github.com/users/ST-DDT/followers","following_url":"https://api.github.com/users/ST-DDT/following{/other_user}","gists_url":"https://api.github.com/users/ST-DDT/gists{/gist_id}","starred_url":"https://api.github.com/users/ST-DDT/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ST-DDT/subscriptions","organizations_url":"https://api.github.com/users/ST-DDT/orgs","repos_url":"https://api.github.com/users/ST-DDT/repos","events_url":"https://api.github.com/users/ST-DDT/events{/privacy}","received_events_url":"https://api.github.com/users/ST-DDT/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/SpongePowered/SpongeAPI/labels/input+wanted","name":"input wanted","color":"fbca04"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":17,"created_at":"2015-01-04T22:13:17Z","updated_at":"2015-01-22T14:39:54Z","closed_at":"2015-01-22T14:39:54Z","body":"I encountered a little problem while looking at the Sponge Implementation and extending existing events.\r\n\r\n**The issue**\r\nI can overwrite every method to return a more precise result than the base interface specifies. However using the Optional destroys that benefit if used the way we currerntly do.\r\n\r\nHere is an example code\r\n````java\r\npublic interface Test {\r\n\r\n    Optional<Test> getSelf();\r\n\r\n    Optional<? extends Test> getBetterSelf();\r\n\r\n}\r\n````\r\nand the second file\r\n````java\r\npublic class Proof implements Test {\r\n\r\n    @Override\r\n    // public Optional<Proof> getSelf() { - NOT POSSIBLE\r\n    public Optional<Test> getSelf() {\r\n        // return Optional.of(this); - NOT POSSIBLE\r\n        return Optional.of((Test) this);\r\n    }\r\n\r\n    @Override\r\n    public Optional<? extends Proof> getBetterSelf() {\r\n        return Optional.of(this);\r\n    }\r\n    \r\n    public void foo() {\r\n        Proof self = getBetterSelf().get();\r\n        // Proof self2 = test.getSelf().get(); - NOT POSSIBLE\r\n        Proof self2 = (Proof) test.getSelf().get();\r\n    }\r\n\r\n}\r\n````\r\nImage the Sponge server itself has  a specific subclass for one of its events, which uses a subclass of the original class/interface because a method was added that is required for further use. So if you listen to the given event and you try to get it, you will actually get the base interface because you have to downcast it, but if you use the `<? extends T>` for example this is no longer an issue you class can simply overwrite the return type and everything will be fine.\r\n\r\nIf we change it we have basically three benefits:\r\n* Avoid unnecessary casting while creating the `Optional`\r\n* Avoid unnecessary casting while getting the `Optional`'s value\r\n* Allow other APIs to extend our API more safely and freely.\r\n\r\nI suggest replacing/changing it in the entire API (where the Optional references a class within the  `org.spongepowered.api.**` package) , i also offer my help to change it.\r\nThis would also include immutable `Iterable`s, `Collection`s, ...., `Map`s.\r\n"},"comment":{"url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/comments/71029388","html_url":"https://github.com/SpongePowered/SpongeAPI/issues/369#issuecomment-71029388","issue_url":"https://api.github.com/repos/SpongePowered/SpongeAPI/issues/369","id":71029388,"user":{"login":"Minecrell","id":3035868,"avatar_url":"https://avatars.githubusercontent.com/u/3035868?v=3","gravatar_id":"","url":"https://api.github.com/users/Minecrell","html_url":"https://github.com/Minecrell","followers_url":"https://api.github.com/users/Minecrell/followers","following_url":"https://api.github.com/users/Minecrell/following{/other_user}","gists_url":"https://api.github.com/users/Minecrell/gists{/gist_id}","starred_url":"https://api.github.com/users/Minecrell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Minecrell/subscriptions","organizations_url":"https://api.github.com/users/Minecrell/orgs","repos_url":"https://api.github.com/users/Minecrell/repos","events_url":"https://api.github.com/users/Minecrell/events{/privacy}","received_events_url":"https://api.github.com/users/Minecrell/received_events","type":"User","site_admin":false},"created_at":"2015-01-22T14:39:53Z","updated_at":"2015-01-22T14:39:53Z","body":"Closing this for the reasons mentioned in #386."}}