Last active
May 20, 2022 22:52
-
-
Save justinmc/112a32907c0d904cfeb84dbca0dadd44 to your computer and use it in GitHub Desktop.
Exploring abstract class vs. mixin for breaking changes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| void main() { | |
| final Abstract implementer = Implementer(); | |
| implementer.foo(); | |
| final Abstract extender = Extender(); | |
| extender.foo(); | |
| final Mixin mixer = MixerWith(); | |
| mixer.bark(); | |
| } | |
| abstract class Abstract { | |
| void foo() { | |
| print('foo'); | |
| } | |
| void bar(); | |
| // Adding a new method with no implementation will break both classes | |
| // that "implement" and "extend" this and don't provide their own | |
| // implementation. | |
| //void breakAll(); | |
| // Adding a new method with an empty implementation will only break classes | |
| // that "implement", but not classes that "extend". | |
| //void breakOne() {} | |
| } | |
| // Must have concrete implementations of both methods. | |
| class Implementer implements Abstract { | |
| // This can't access Abstract.foo I don't think. | |
| // Needs an implementation of foo even though one was provided in Abstract. | |
| void foo() { | |
| print('foo from Implementer'); | |
| //return super.foo(); | |
| } | |
| // And needs an implmemenation of bar as well. | |
| void bar() { | |
| print('bar from Implementer'); | |
| } | |
| } | |
| // Only needs a concrete implementation of bar. | |
| class Extender extends Abstract { | |
| // Must have an implementation of bar because none was given in Abstract. | |
| void bar() { | |
| print('bar from Extender'); | |
| } | |
| // Doesn't need an implementation for foo. | |
| } | |
| mixin Mixin { | |
| void baz(); | |
| void bark() { | |
| print('bark'); | |
| } | |
| // Adding a new method with no implementation will break both | |
| // classes that use "with" and "implements" and don't provide | |
| // their own implementation. | |
| //void breakIt(); | |
| // Adding a new method with an empty implementation will break | |
| // only classes that use "implements", not classes that use "with". | |
| //void breakOne() {} | |
| } | |
| // Cannot extend a mixin, only implement or with. | |
| class MixerWith with Mixin { | |
| // Must have a concrete implementation of baz. | |
| void baz() { | |
| print('baz from MixerWith'); | |
| } | |
| // Doesn't need one for bark. | |
| } | |
| class MixerExtends implements Mixin { | |
| // Must have a concrete implementation of baz and bark. | |
| void baz() { | |
| print('baz from MixerExtends'); | |
| } | |
| void bark() { | |
| print('bark from MixerExtends'); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment