Last active
March 6, 2022 10:24
-
-
Save Luoyayu/9889bb1d451ac78ff1973b177ed5f3e3 to your computer and use it in GitHub Desktop.
Tour of Dart: A simple Mixin example about printer
This file contains 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
/// Tour of Dart | |
/// A simple Mixin example about printer. | |
class Paper { | |
String sizeName = 'Paper'; | |
// bool printable = false; | |
// Paper(this.sizeName, this.printable); | |
/// Here we don't care whether Paper can be printed, | |
/// and what can be printed may not be Paper, or film. | |
/// We use Mixin onto [Printable] and | |
/// unique [PaperPrinting] when the subclass inherits [Paper]. | |
Paper(this.sizeName); | |
} | |
/// [Film] can also be printed. | |
class Film { | |
String sizeName = 'Film'; | |
// bool printable = true; | |
} | |
/// Printable protocol: | |
/// caller must implement [callPrinter] in two ways: | |
/// 1. abstract class Printable { void callPrinter(); } | |
/// 2. mixin Printable { void callPrinter(); } | |
/// I think the first one is clearer, declared as an interface: | |
/// the object provided must be *extends* or *with* [Printable] | |
/// The second way is equivalent to a protocol: | |
/// the object provided must *with* [Printable] | |
abstract class Printable { | |
void callPrinter(); | |
} | |
/// The function we want to define like: | |
void printContent(Printable user) { | |
user.callPrinter(); | |
} | |
typedef Context = Map<String, dynamic>; | |
/// The successor to [PaperPrinting] | |
/// must inherit from [Paper] or implement the related protocol, | |
/// which is equivalent to *where* in *Swift* | |
/// *on* [Printable] is optional, but declaring it helps to display overloads. | |
mixin PaperPrinting on Paper, Printable { | |
bool printable = true; | |
/// Print management [Context] | |
Context ctx = {}; | |
/// Printable protocol: [callPrinter] | |
@override | |
void callPrinter() { | |
var printerId = applyPrinter(ctx); | |
sendTaskToPrinter(ctx, printerId, prepareContent()); | |
taskFinishCallback(ctx); | |
} | |
// General process: apply for printer queue protocol | |
int applyPrinter(Context ctx) { | |
// ... system call for printer queue. | |
var printerId = 0x666; | |
ctx['applied'] = true; | |
ctx['printer_id'] = printerId; | |
return printerId; | |
} | |
/// General process: send task to printers | |
void sendTaskToPrinter(Context ctx, int printerId, String content) { | |
// ... Completed a series of tasks. | |
/// Update state of printer's context | |
ctx.putIfAbsent('finished', () => true); | |
} | |
/// The content to be printed is provided by the subclass | |
String prepareContent(); | |
/// Callback function is provided by subclass | |
void taskFinishCallback(Context ctx); | |
} | |
class DraftPaper extends Paper { | |
DraftPaper({String sizeName = 'Draft Paper'}) : super(sizeName); | |
} | |
/// The order of *with* | |
/// the latter and the definition body provide the implementation for the former. | |
/// [PaperPrinting] in [PhotoPaper] implements the necessary [callPrinter]. | |
class PhotoPaper extends Paper with Printable, PaperPrinting { | |
PhotoPaper({String sizeName = 'A6 Photo Paper'}) : super(sizeName); | |
@override | |
String prepareContent() => "...Content..."; | |
@override | |
void taskFinishCallback(ctx) { | |
print(ctx['finished'] as bool | |
? "printing service using $sizeName." | |
: "May I try printer again?"); | |
} | |
} | |
mixin FilmPrinting on Film, Printable { | |
@override | |
void callPrinter() => print('???'); | |
} | |
/// we can implement [callPrinter] directly in [ExampleFilm] inherited from [Film] | |
class ExampleFilm extends Film with Printable { | |
@override | |
void callPrinter() => print("printing service using Example Film."); | |
} | |
void test() { | |
printContent(PhotoPaper()); | |
printContent(ExampleFilm()); | |
// ERROR: 'DraftPaper' can't be assigned to 'Printable'. | |
// printContent(DraftPaper()); | |
/* Output: | |
printing service using A6 Photo Paper. | |
printing service using Example Film. | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment