//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');
}
}
}
понедельник, 12 апреля 2021 г.
OOP
Подписаться на:
Комментарии к сообщению (Atom)
Комментариев нет:
Отправить комментарий