abstract class IShape {
void getArea();
}
class Shape implements IShape {
double area;
Shape(this.area);
@override
void getArea() {
print(area);
}
}
class Rect extends Shape {
double w, h;
Rect(this.w, this.h) : super(w * h);
}
class Circle extends Shape {
double radius;
Circle(this.radius) : super(3.14 * radius * radius);
}
class Canvas implements IShape {
var shapes = <IShape>[];
@override
void getArea() {
for (var shape in shapes) {
shape.getArea();
}
}
}
void main() {
final canvas = Canvas();
canvas.shapes = [
Rect(5, 5),
Circle(3),
];
canvas.getArea();
}
Dart
вторник, 27 апреля 2021 г.
Composite
воскресенье, 25 апреля 2021 г.
Template Method
abstract class SoundSystem {
void makeSound() {
print(getSound());
}
String getSound();
}
class DVDPlayer extends SoundSystem {
@override
String getSound() {
return 'Play DVD disk';
}
}
class Radio extends SoundSystem {
@override
String getSound() {
return 'Play radio station';
}
}
void main() {
final systems = <SoundSystem>[
DVDPlayer(),
Radio(),
];
for (var system in systems) {
system.makeSound();
}
}
Adapter
abstract class ITemperatureAdapter {
String getTemperature();
}
class CelsiusAdapter implements ITemperatureAdapter {
double cel;
CelsiusAdapter(this.cel);
@override
String getTemperature() {
return 'Fahrenheit: ${C2F(cel)}';
}
double C2F(double cel) {
return (cel * 9 / 5) + 32;
}
}
class FahrenheitAdapter implements ITemperatureAdapter {
double far;
FahrenheitAdapter(this.far);
@override
String getTemperature() {
return 'Celsius: ${F2C(far)}';
}
double F2C(double far) {
return (far - 32) * 5 / 9;
}
}
void main() {
printTemp(CelsiusAdapter(10));
printTemp(FahrenheitAdapter(104));
}
void printTemp(ITemperatureAdapter adapter) {
print(adapter.getTemperature());
}
суббота, 24 апреля 2021 г.
Singleton
//Classic way
class Manager1 {
static Manager1? _instance; //null
Manager1._internal() {
print('new instance of Manager1 constructed');
}
static Manager1? getInstance() {
_instance ??= Manager1._internal();
return _instance;
}
}
//Dart way
class Manager2 {
static final Manager2 _instance = Manager2._internal();
Manager2._internal() {
print('new instance of Manager2 constructed');
}
factory Manager2() {
return _instance;
}
}
void main() {
final m1 = Manager1.getInstance(); //new instance of Manager1 constructed
final m2 = Manager1.getInstance();
final m3 = Manager2(); //new instance of Manager2 constructed
final m4 = Manager2();
}
вторник, 13 апреля 2021 г.
Asynchronous
//Dart is a single-threaded language.
//Future - promise to give you the value later.
void main() {
//Callbacks
print('Start'); //1
Future<int>.delayed(Duration(seconds: 3), () => 7)
.then(
(value) => print('Value: $value'), //3
)
.catchError(
(error) => print('Error: $error'),
)
.whenComplete(
//run after value or error
() => print('Ready!'), //4
);
print('End'); //2
//async-await
print('Start2'); //synchronous function
main2(); //asynchronous function - promise to give you the value later.
print('End2'); //synchronous function
//try-catch - error handling
print('Start3');
main3();
print('End3');
}
//asynchronous function
Future<void> main2() async {
final value = await Future<int>.delayed(Duration(seconds: 2), () => 7);
//the rest of the function won’t run until the future completes
print('Value2: $value');
print('Ready2!');
}
//try-catch - error handling
Future<void> main3() async {
try {
//throw Exception('error'); //error testing
final value = await Future<int>.delayed(Duration(seconds: 1), () => 7);
//the rest of the function won’t run until the future completes
print('Value3: $value');
} catch (error) {
print(error);
} finally {
print('Ready3!'); //run after value or error
}
}
понедельник, 12 апреля 2021 г.
OOP
//Inheritance, Interfaces, Polymorphism, mixins
void main() {
//Inheritance, "is, is! (is not)"-operators
//Only one class can be inherited
final st1 = Student('Tom', 'USA', 'German');
print('Type: ' + st1.runtimeType.toString());
print('isObject: ' + (st1 is Object).toString());
print('isPerson: ' + (st1 is Person).toString());
print('isStudent: ' + (st1 is Student).toString());
print('isNotTeacher: ' + (st1 is! Teacher).toString());
final st2 = Student('Mike', 'UK', 'Math');
final tch1 = Teacher('Fred', 'France', 'Art');
//Polymorphism - A Student is a Person
//But prefer composition over inheritance!
//It’s more of what an object HAS,
//than what an object IS.
final persons = <Person>[st1, st2, tch1];
for (var person in persons) {
print(person);
}
//Abstract classes - can't instantiate
//final sh1 = Shape(); //error!
final sq1 = Square(size: 5);
final cr1 = Circle(radius: 5);
//Polymorphism - Square and Circle are Shapes
final shapes = <Shape>[sq1, cr1];
for (var shape in shapes){
if (shape is Square){
print('I am ${shape.runtimeType}! With size: ${shape.size}. My area is: ${shape.area()}');
} else if (shape is Circle){
print('I am ${shape.runtimeType}! With radius: ${shape.radius}. My area is: ${shape.area()}');
} else {
print('I am ${shape.runtimeType}! My area is: ${shape.area()}');
}
}
//Interfaces
//Many interfaces cam be inherited
final iDrawable sp1 = Sprite();
sp1.draw();
(sp1 as iUpdatable).update(); //as - casting
//Factory constructor -
//to keep the implementation details separate from the business logic.
//Nothing changes here
final someSubClass = FactoryClass();
someSubClass.interface();
//Mixins
//Many mixins cam be inherited
final mDrawable sp2 = Sprite1();
sp2.draw();
(sp2 as mUpdatable).update();
final mUpdatable ph1 = Physics();
ph1.update();
//Extension methods
st1.hi();
st2.hi();
print(5.doubled);
print('Monday is a workday: ${Days.Monday.isWorkDay}');
}
//Parent (super) class
class Person {
Person(this.name, this.country);
String name;
String country;
String get info => 'My name is $name, I am from $country.';
@override
String toString() => info;
}
//Inheritance, "extends" keyword
//override properties and methods, super
//Child (sub) class
class Student extends Person {
Student(String name, String country, this.subject) : super(name, country);
String subject;
@override
String get info => '${super.info} I am learning $subject.';
}
class Teacher extends Person {
Teacher(String name, String country, this.subject) : super(name, country);
String subject;
@override
String get info => '${super.info} I am teaching $subject.';
}
//Abstract classes
abstract class Shape {
Point center = Point();
double area(); //abstract method
}
class Square extends Shape {
Square({required this.size});
final double size;
@override //implements abstract methods
double area() => size * size;
}
class Circle extends Shape {
Circle({required this.radius});
final double radius;
@override //implements abstract methods
double area() => 3.14 * radius * radius;
}
class Point{
int x = 0, y = 0;
}
//Interfaces, "implements" keyword
//When you extend GameObj, Sprite has access to any methods or variables in GameObj.
//If Sprite implements iDrawable and iUpdatable, Sprite must provide its own version
//of all methods and variables in iDrawable and iUpdatable.
class GameObj {
}
abstract class iDrawable { //Interface
late Point center; //late - initialises when instantiates
void draw();
}
abstract class iUpdatable { //Interface
void update();
}
class Sprite extends GameObj implements iDrawable, iUpdatable {
@override
Point center = Point();
@override
void draw() { //need implementation
}
@override
void update() { //need implementation
}
}
//Factory constructor, can return subclass!!!
//to keep the implementation details separate from the business logic
//Changes live here
abstract class FactoryClass { //Interface - see to user
factory FactoryClass() => SubClass1();
//factory FactoryClass() => SubClass2();
//factory FactoryClass() => SubClass3();
void interface();
}
class SubClass1 implements FactoryClass { //Concrete class - hide from user
@override
void interface() {
print('I am $runtimeType');
}
}
//Mixins, "with" keyword
//You can use concrete or abstract class as a mixin,
//but "mixin" keyword indicates that...
mixin mDrawable { //this class can only be used as mixin
void draw() {
print('Default draw');
}
}
mixin mUpdatable { //this class can only be used as mixin
void update() {
print('Default update');
}
}
class Sprite1 extends GameObj with mDrawable, mUpdatable {
//do not need implementation of the draw and update methods
}
class Physics extends GameObj with mUpdatable{
//we can use realisation from mixin class
}
//Extension methods
//we can extend String, int, ...
//name MyExt is optional
extension _MyExt on Person {
void hi(){
print('Hi $name');
}
}
extension on int {
int get doubled {
return this * this;
}
}
enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
extension on Days {
bool get isWorkDay {
switch (this) {
case Days.Monday:
case Days.Tuesday:
case Days.Wednesday:
case Days.Thursday:
case Days.Friday:
return true;
case Days.Saturday:
case Days.Sunday:
return false;
default:
throw Exception('Unknown weekday $this');
}
}
}
пятница, 9 апреля 2021 г.
Functional
//Higher order methods
//map(), where(), every(), reduce(), fold() and sort().
void main() {
var numbers = [1, 2, 3, 4, 5];
//map()
var sq1 = [];
for(var element in numbers){
sq1.add(element * element);
}
print(sq1);
final sq2 = numbers.map((element) => element * element).toList();
print(sq2);
//where() - filter
var even1 = [];
for(var element in numbers){
if (element.isEven) {
even1.add(element);
}
}
print(even1);
final even2 = numbers.where((element) => element.isEven).toList();
print(even2);
//every()
bool? isGood1;
for(var element in numbers){
if (element == 3) {
isGood1 = false;
break;
}
isGood1 = true;
}
print(isGood1);
final isGood2 = numbers.every((element) => element != 3);
print(isGood2);
//reduce()
var sum1 = 0;
for (var element in numbers) {
sum1 += element;
}
print(sum1);
final total1 = numbers.reduce((value, element) => value + element);
print(total1);
//fold()
var strings = ['a', 'bb', 'ccc', 'dddd', 'eeeee'];
var sum2 = 0;
for (var element in strings) {
sum2 += element.length;
}
print(sum2);
final total2 = strings.fold(0, (value, element) => (value as int) + element.length);
print(total2);
//sort()
var list1 = [3, 5, 1, 4, 2];
list1.sort();
print(list1);
//Comparable
var list2 = ['c', 'a', 'b'];
list2.sort();
print(list2);
//Comparator
var list3 = ['ccc', 'a', 'bb'];
list3.sort((prev, next) => prev.length.compareTo(next.length));
print(list3);
//Custom Types
var points = [Point(3, 1), Point(1, 3), Point(2, 2)];
//Comparable
points.sort();
print(points);
//Comparator
points.sort((prev, next) => prev.y.compareTo(next.y));
print(points);
//reversed property
var reversedNumbers = numbers.reversed.toList();
print(reversedNumbers);
//Combining methods
final seven = numbers.where((element) => (element % 2) == 0)
.where((element) => element == 4)
.map((e) => e + 3).first;
print(seven);
}
class Point implements Comparable<Point>{
Point(this.x, this.y);
final x;
final y;
@override
bool operator ==(Object other) {
return (other is Point) && other.x == x && other.y == y;
}
//Comparable
//The function must return an integer.
// If the result is negative, the first value will be placed before the second value.
// Otherwise, the second value will appear before the first value in the sorted List.
// If the result is 0, it means both values are equal in the ordering.
@override
int compareTo(Point other) {
return x - other.x;
}
@override
int get hashCode => x.hashCode ^ y.hashCode;
@override
String toString() {
return 'Point (x: $x, y: $y)';
}
}