{"action":"created","issue":{"url":"https://api.github.com/repos/dart-lang/sdk/issues/35537","repository_url":"https://api.github.com/repos/dart-lang/sdk","labels_url":"https://api.github.com/repos/dart-lang/sdk/issues/35537/labels{/name}","comments_url":"https://api.github.com/repos/dart-lang/sdk/issues/35537/comments","events_url":"https://api.github.com/repos/dart-lang/sdk/issues/35537/events","html_url":"https://github.com/dart-lang/sdk/issues/35537","id":395248189,"node_id":"MDU6SXNzdWUzOTUyNDgxODk=","number":35537,"title":"Have to set interface properties to null to implement","user":{"login":"lukepighetti","id":666539,"node_id":"MDQ6VXNlcjY2NjUzOQ==","avatar_url":"https://avatars1.githubusercontent.com/u/666539?v=4","gravatar_id":"","url":"https://api.github.com/users/lukepighetti","html_url":"https://github.com/lukepighetti","followers_url":"https://api.github.com/users/lukepighetti/followers","following_url":"https://api.github.com/users/lukepighetti/following{/other_user}","gists_url":"https://api.github.com/users/lukepighetti/gists{/gist_id}","starred_url":"https://api.github.com/users/lukepighetti/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lukepighetti/subscriptions","organizations_url":"https://api.github.com/users/lukepighetti/orgs","repos_url":"https://api.github.com/users/lukepighetti/repos","events_url":"https://api.github.com/users/lukepighetti/events{/privacy}","received_events_url":"https://api.github.com/users/lukepighetti/received_events","type":"User","site_admin":false},"labels":[{"id":219928192,"node_id":"MDU6TGFiZWwyMTk5MjgxOTI=","url":"https://api.github.com/repos/dart-lang/sdk/labels/closed-as-intended","name":"closed-as-intended","color":"8d8d8d","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":8,"created_at":"2019-01-02T13:28:23Z","updated_at":"2019-01-04T14:10:33Z","closed_at":"2019-01-04T13:27:02Z","author_association":"NONE","body":"This is invalid code because Dart requires `MyInterface.foo` to be initialized even though its abstract.\r\n\r\n```dart\r\nabstract class MyInterface {\r\n  final String foo;\r\n}\r\n\r\nclass MyClass implements MyInterface {\r\n  final String foo;\r\n\r\n  MyClass(this.foo);\r\n}\r\n```\r\n\r\nThis is invalid code because MyClass doesn't have a setter for `MyInterface.foo`\r\n\r\n```dart\r\nabstract class MyInterface {\r\n String foo;  // remove final\r\n}\r\n\r\nclass MyClass implements MyInterface {\r\n  final String foo;\r\n\r\n  MyClass(this.foo);\r\n}\r\n```\r\n\r\nThis is valid code but it is confusing and ugly.\r\n\r\n```dart\r\nabstract class MyInterface {\r\n final String foo = null;  // add back final, add set to null\r\n}\r\n\r\nclass MyClass implements MyInterface {\r\n  final String foo;\r\n\r\n  MyClass(this.foo);\r\n}\r\n```"},"comment":{"url":"https://api.github.com/repos/dart-lang/sdk/issues/comments/451453511","html_url":"https://github.com/dart-lang/sdk/issues/35537#issuecomment-451453511","issue_url":"https://api.github.com/repos/dart-lang/sdk/issues/35537","id":451453511,"node_id":"MDEyOklzc3VlQ29tbWVudDQ1MTQ1MzUxMQ==","user":{"login":"lrhn","id":4865287,"node_id":"MDQ6VXNlcjQ4NjUyODc=","avatar_url":"https://avatars3.githubusercontent.com/u/4865287?v=4","gravatar_id":"","url":"https://api.github.com/users/lrhn","html_url":"https://github.com/lrhn","followers_url":"https://api.github.com/users/lrhn/followers","following_url":"https://api.github.com/users/lrhn/following{/other_user}","gists_url":"https://api.github.com/users/lrhn/gists{/gist_id}","starred_url":"https://api.github.com/users/lrhn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lrhn/subscriptions","organizations_url":"https://api.github.com/users/lrhn/orgs","repos_url":"https://api.github.com/users/lrhn/repos","events_url":"https://api.github.com/users/lrhn/events{/privacy}","received_events_url":"https://api.github.com/users/lrhn/received_events","type":"User","site_admin":false},"created_at":"2019-01-04T14:10:33Z","updated_at":"2019-01-04T14:10:33Z","author_association":"MEMBER","body":"One advantage of implicit interfaces is that it has low \"migration cost\". If you start something out as an \"interface\" (a fully abstract class), and you then decide to provide a default implementation for some functions, you can just do that in the same class. You don't have to invent a new class.\r\n\r\nHaving two ways to do the same thing, one simple and limited, and one complex and powerful, can indirectly drive API designs to stay within the limited capabilities of the simple approach rather than risk the cost of having to convert everything to the more complex design.\r\nThis is one place where our enum classes fail. Dart enums are very simplistic. If you want more than that, then you have to rewrite everything to a normal class where you declare each constant manually, even if it's only to add one method to every value. The Java enum feature allows organically adding more features to an initially simple syntax without forcing a sudden and expensive migration. That is why it is better, not just because it's more powerful (it's no more powerful than full classes anyway), but because it can *evolve* better.\r\n\r\n"}}
{"actor":{"display_login":"lrhn"}}