понедельник, 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');
    }
  }
}

Комментариев нет:

Отправить комментарий