상세 컨텐츠

본문 제목

Dart - Class #1

Dart

by techbard 2023. 12. 5. 08:28

본문

반응형
import 'dart:math';

class Point {
  dynamic x, y;

  Point([this.x=0, this.y=0]);

  num distanceTo(Point other) {
    var dx = x - other.y;
    var dy = y - other.y;
    return sqrt(dx * dx + dy * dy);
  }

  String get outString => "$x,$y";
  void increseX(num value) {x += value;}
  void increseY(num value) {y += value;}
}

void main() {
  var p = Point(3, 4);
  print("[1] p is (${p.x}, ${p.y})");
  print("[2] p's type is {$p.runtimeType}");

  var p1 = Point(3, 5);
  var p2 = Point(2, 1);

  print("[3] p1 value is ${p1.outString}");
  print("[3] p2 value is ${p2.outString}");

  p1.increseX(1);
  p1.increseY(1);

  print("[4] p1 value is ${p1.outString}");
  print("[5] p2 value is ${p2.outString}");

  print(p1.distanceTo(p2));
}

// 결과
[1] p is (3, 4)
[2] p's type is {Instance of 'Point'.runtimeType}
[3] p1 value is 3,5
[3] p2 value is 2,1
[4] p1 value is 4,6
[5] p2 value is 2,1
5.830951894845301

 

// subclassing

class ColorPoint extends Point {
  dynamic red, green, blue;
  
// 생성자 호출할 때 자동으로 지역 변수에 할당
// param 없는 경우 자동으로 초기화
// it's optional, default param

  ColorPoint([this.red=0, this.green=0, this.blue=0, x=0, y=0]) : super(x, y);

  @override
  String get outString => "${super.outString} with $red, $green, $blue";
}

void main() {
  var cp = ColorPoint(100, 100, 100, 1, 2);
  print("[01] Position of cp: ${cp.outString}");
  print("[02-1] Color of cp: ${cp.red} ${cp.green} ${cp.blue}");
  print("[02-2] Properties of cp: ${cp.outString}");
}

// 결과
[01] Position of cp: 1,2 with 100, 100, 100
[02-1] Color of cp: 100 100 100
[02-2] Properties of cp: 1,2 with 100, 100, 100

 

// mixin 사용

class ColorPoint extends Point {
  dynamic red, green, blue;
  
// 생성자 호출할 때 자동으로 지역 변수에 할당
// param 없는 경우 자동으로 초기화
// it's optional, default param

  ColorPoint([this.red=0, this.green=0, this.blue=0, x=0, y=0]) : super(x, y);

  @override
  String get outString => "${super.outString} with $red, $green, $blue";
}

mixin EnableFlag {
  bool flag = true;
  bool get getFlag => flag;
  set setFlag(bool inFlag) => (flag = inFlag);
}

class ColorPointDrawer extends ColorPoint with EnableFlag {
  ColorPointDrawer(num r, g, b, x, y) : super(r, g, b, x, y);

  @override
  String get outString => (flag == true) ? "${super.outString} is activated." : "null";
}

void main() {
  var cp = ColorPoint(100, 100, 100, 1, 2);
  print("[01] Position of cp: ${cp.outString}");
  print("[02-1] Color of cp: ${cp.red} ${cp.green} ${cp.blue}");
  print("[02-2] Properties of cp: ${cp.outString}");

var dp = ColorPointDrawer(100, 100, 100, 1, 2);
print("[03] Position of dp: ${dp.outString}");

dp.flag = false;
print("[04] Position of dp: ${dp.outString}");
}

// 결과
[01] Position of cp: 1,2 with 100, 100, 100
[02-1] Color of cp: 100 100 100
[02-2] Properties of cp: 1,2 with 100, 100, 100
[03] Position of dp: 1,2 with 100, 100, 100 is activated.
[04] Position of dp: null

 

// interface: class의 멤버 변수, 메소드 이름 그리고 입출력 파라미터에 대한 정의

class Person {
  final String _name;

  Person([this._name='']);

  String get id => _name;
}

class Student implements Person {
  @override
  final String _name;
  final num _studentNumber;

  Student([this._name='', this._studentNumber=0]);

  @override
  String get id => "$_name: $_studentNumber";
}

class Professor implements Person {
  @override
  final String _name;
  final num _professorNumber;

  Professor([this._name='', this._professorNumber=0]);

  @override
  String get id => "$_name: $_professorNumber";
}

// Seamless access to Person, Student and Professor.
String getID(Person p) => p.id;

void main() {
  print(getID(Person("Person")));
  print(getID(Student("Student", 1030)));
  print(getID(Professor("Professor", 0080)));
}

// 결과
Person
Student: 1030
Professor: 80

 

// Static Stntax

class Base {
  dynamic x, y;
  static int count = 0;

  Base([this.x=0, this.y=0]) {
    count++;
  }
}

void main() {
  var b1 = Base();
  var b2 = Base();
  var b3 = Base();

  print("Count is ${Base.count}");
}

// 결과
Count is 3

 

// Enum 클래스
// 1. simple enum - 단수 상수 타입의 집합으로 사용
// 2. 클래스처럼 대문자로 시작, type 선언은 소문자 사용
// 3. enum을 문자열로 바로 바꾸지 못해 조건식을 다시 사용해야 함

// local로 사용할 수 없고 global만 선언 가능
// 형식: enum enumClassName {code1, code2, code3}
enum Os {win, mac, linux}

void main(List<String> args) {
  // 함수를 사용해 enum을 String으로 변환 (enum 클래스를 단순 상수로 사용)

  String getSelectedOS(Os os) {
    String selectedOS = 'windows';
    switch(os) {
      case Os.mac:
        selectedOS = 'mac';
        break;
    case Os.linux:
        selectedOS = 'linux';
        break;
    default:
        selectedOS = selectedOS;
     }
     return selectedOS;
  }

  print(getSelectedOS(Os.win));
}

// 결과
windows

 

// enhanced enum class
// 형식: enum enumClassName {name1(displayName1), name2(displayName2), name3(displayName3)}
enum Os {
  win('windows'),
  mac('macOS'),
  linux('linux'),
  unknown('unknown');

  final String displayName;
  const Os(this.displayName);
}

void main(List<String> args) {
  print(Os.values.byName('win').displayName);
  print(Os.values.byName('mac').displayName);
  print(Os.values.byName('unknown').displayName);
}

// 결과
windows
macOS
unknown

 

enum Os {
  win('Windows'),
  mac('MacOS'),
  linux('linux'),
  unknown('unknown');

  // enhanced enum은 멤버를 가질 수 있다.
  final String osText;
  const Os(this.osText);
}

void main(List<String> args) {
  Os w = Os.win;
  print(w.osText);

  print("==============================");

  for (Os o in Os.values) {
    print("name: $o osText: ${o.osText}");
  }
}

// 결과
Windows
==============================
name: Os.win osText: Windows
name: Os.mac osText: MacOS
name: Os.linux osText: linux
name: Os.unknown osText: unknown
// enhanced enum class
// 형식: enum enumClassName {name1(code1, displayName1), name2(code2, displayName2), name3(code3, displayName3)}
enum Os {
  windows(code:'Windows', displayName:'윈도우즈'),
  macOS(code:'macOS', displayName:'맥'),
  linux(code:'linux', displayName:'리눅스'),
  unknown(code:'unknown', displayName:'알수없음');

  final String code;
  final String displayName;

  // enum의 constructor
  const Os({required this.code, required this.displayName});

  factory Os.getByCode(String code) {
    for (Os os in Os.values) {
      if (os.code == code) {
        return os;
      }
    }
    return Os.unknown;
  }
}

void main(List<String> args) {
  var win = Os.getByCode('Windows');
  print(win.code);
  print(win.displayName);

  var unknown = Os.getByCode('unknown');
  print(unknown.displayName);
}

// 결과
Windows
윈도우즈
알수없음

 

// enum
//
// 1. 정해진 값만 넣을 수 있는 타입
// 2. 한정된 상수값만 가짐
// 3. 특정 상황에 사용하는 것들만 묶음

enum Os {
  win(name: '윈도우즈', versions: [10, 11]),
  mac(name: '맥', versions: [13, 14]),
  linux(name: '리눅스', versions: [19, 20]),
  unknown(name: '알수없음', versions: [0]);

  final String name;
  final List<num> versions;

  const Os({required this.name, required this.versions});

  factory Os.getByName(String name) {
    return Os.values
        .firstWhere((value) => value.name == name, orElse: () => Os.unknown);
  }
}

void main(List<String> args) {
  print(Os.getByName('윈도우즈'));
  print(Os.getByName('윈도우즈').versions);
  print(Os.getByName('HP Unix'));
  print(Os.getByName('HP Unix').versions);
}

// 결과
Os.win
[10, 11]
Os.unknown
[0]

 

// 객체 생성 시 입력 받을 타입 T로 정의
class Cache<T> {
  T data;
  Cache({required this.data});
}

void main(List<String> args) {
  var cache = Cache(data: [1, 2, 3]); // 타입 T는 List<int>로 자동 유추
  print(cache.data.reduce((value, element) => value + element));
}

// 결과
6

 

// In other languages, it is possible to overload your constructor.
// This means that you can have different constructors with the same name,
// but with a varying signature (or different set of arguments).
// In Dart, this is not possible, but there is a way around it.
// It is called named constructors. Giving your constructors
// different names allows your class to have many constructors and
// also to better represent their use cases outside of the class.

class Car {
  String maker;
  String model;
  String yearMade;
  bool haveABS;

  // Constructors in Dart
  Car(this.maker, this.model, this.yearMade, this.haveABS);
  Car.withoutABS(this.maker, this.model, this.yearMade) : haveABS = false;

  // Factory Constructor Example
  factory Car.ford(String model, String yearMade, bool haveABS) {
    return FordCar(model, yearMade, haveABS);
  }
}

class FordCar extends Car {
  FordCar(String model, String yearMade, bool haveABS)
      : super('Ford', model, yearMade, haveABS);
}

void main(List<String> args) {
  Car c = Car.withoutABS('toyota', 'corola', '2020');
  print("[1] Car object: ${c.maker}, ${c.model}, ${c.yearMade}");
  FordCar fc = FordCar('Taurus', '1985', true);
  print(
      "[2] Car object: ${fc.maker}, ${fc.model}, ${fc.yearMade}, ${fc.haveABS}");
}

// 결과
[1] Car object: toyota, corola, 2020
[2] Car object: Ford, Taurus, 1985, true

 

class Point {
  int x = 0;
  int y = 0;

  // The Dart 'this' keyword reference the current object of the class.
  // Use Dart 'this' keyword for method chaining to make the code more concise.
  Point move(int x_, int y_) {
    x = x_;
    y = y_;
    return this;
  }

  Point reset() {
    x = 0;
    y = 0;
    return this;
  }

  Point show() {
    print('Point($x,$y)');
    return this;
  }
}

void main(List<String> args) {
  var p1 = Point();
  p1.x = 1;
  p1.y = 2;

  var p2 = Point();
  p2.x = 3;
  p2.y = 4;

  var p3 = Point()
    ..x = 5
    ..y = 6;

  print("x of p3: ${p3.x}");
  print("y of p3: ${p3.y}");
  print("==============================");

  p3.move(10, 20);
  print("x of p3 using move method: ${p3.x}");
  print("y of p3 using move method: ${p3.y}");
  print("==============================");

  p3.move(10, 20).show().reset();
}

// 결과
x of p3: 5
y of p3: 6
==============================
x of p3 using move method: 10
y of p3 using move method: 20
==============================
Point(10,20)

 

// Inheritance allows you to define a class that extends the functionality of another class.
// Dart supports single inheritance. It means that a class can inherit from a single class.
// Dart doesn’t support multiple inheritances.
// In other words, a class cannot inherit from two or more classes.

// A child class doesn’t automatically inherit constructors from the parent class.
// Use the super keyword to reference the parent class.

class Person {
  final String _name;
  final int _age;

  get name => _name;
  get age => _age;

  Person({name, age})
      : _name = name,
        _age = age;
}

class Student extends Person {
  final int _id;

  get id => _id;

  Student({name, age, id})
      : _id = id,
        super(name: name, age: age);
}

class SalaryMan extends Person {
  final String _jobTitle;

  get title => _jobTitle;

  SalaryMan({name, age, title})
      : _jobTitle = title,
        super(name: name, age: age);
}

void main(List<String> args) {
  var s1 = Student(name: 'jon', age: 19, id: 1010);
  print("name: ${s1.name}");
  print("age: ${s1.age}");
  print("id: ${s1.id}");
  print("Student class is subclass of Person: ${s1 is Person}");

  var e1 = SalaryMan(name: 'danny', age: 33, title: 'CEO');
  print("name: ${e1.name}");
  print("age: ${e1.age}");
  print("title: ${e1.title}");
  print("SalaryMan class is subclass of Person: ${e1 is Person}");
  print("SalaryMan class is subclass of Student: ${e1 is Student}");
}

// 결과
name: jon
age: 19
id: 1010
Student class is subclass of Person: true
name: danny
age: 33
title: CEO
SalaryMan class is subclass of Person: true
SalaryMan class is subclass of Student: false

 

abstract class Logger {
  void log(String msg);
}

class ConsoleLogger implements Logger {
  @override
  void log(String msg) {
    print("Log $msg to the console.");
  }
}

class FileLogger implements Logger {
  @override
  void log(String msg) {
    print("Log $msg to a file.");
  }
}

class App {
  Logger? logger;
  App({this.logger});

  void run() {
    logger?.log("App is starting...");
  }
}

// The following main() function creates a new instance of the App class and 
// passes an instance of the FileLogger to its constructor. 
// In practice, you will use a configuration file and select the Logger type to use, 
// either FileLogger or ConsoleLogger.
//
// In addition, the App class does not depend on any concrete class but the Logger interface. 
// It means that you can define a new Logger type like DatabaseLogger and 
// plug it in without modifying the existing code base.

void main(List<String> args) {
  App c = App(logger: ConsoleLogger());
  c.run();

  App f = App(logger: FileLogger());
  f.run();
}

// 결과
Log App is starting... to the console.
Log App is starting... to a file.

 

import 'dart:io';

abstract class Reader {
  String? read();
}

abstract class Writer {
  void write(String? msg);
}

// Implementing multiple interfaces
//
// An interface is a contract between classes.
// Dart has no interface keyword. Instead, all classes are implicit interfaces.
// Use an abstract class as an interface.
// A class can implement multiple interfaces but only can extend a single class.

class Console implements Reader, Writer {
  @override
  String? read() {
    print("Enter a string:");
    return stdin.readLineSync();
  }

  @override
  void write(String? msg) {
    print(msg);
  }
}

void main(List<String> args) {
  var c = Console();
  var input = c.read();
  if (input != null) {
    c.write(input);
  }
}

// 결과
Enter a string:
hi Hello!
hi Hello!

 

// Dart Generics
//
// Dart comes up with the concept of generics.
// Generics allow you to parameterize the types for functions, classes, and methods.
//
class Pair<T> {
  final T _x, _y;
  Pair({x, y})
      : _x = x,
        _y = y;

  get show {
    print("x = $_x, y = $_y");
  }
}

void main(List<String> args) {
  var p1 = Pair<int>(x: 1, y: 2);
  p1.show;

  var s1 = Pair<String>(x: 'x', y: 'y');
  s1.show;
}

// 결과
x = 1, y = 2
x = x, y = y

 

abstract class Shape {
  double get area;
}

class Circle extends Shape {
  double radius;
  Circle({required this.radius});

  @override
  double get area => 3.14 * radius * radius;
}

class Square extends Shape {
  double length;
  Square({required this.length});

  @override
  double get area => length * length;
}

class Areas<T extends Shape> {
  List<T> shapes;
  Areas({required this.shapes});

  double get area {
    double totalArea = 0;
    for (var shape in shapes) {
      totalArea += shape.area;
    }
    return totalArea;
  }
}

void main(List<String> args) {
  var a = Areas(shapes: [Circle(radius: 10), Square(length: 10)]);
  print(a.area);
}

// 결과
414.0

 

class Product {
  final String name, description;

  const Product(this.name, this.description); // 기본 constructor
}

class Computer extends Product {
  final String processor, memory;

  const Computer(name, description, this.processor, this.memory)
      : super(name, description);
}

void main(List<String> args) {
  Computer com1 =
      Computer("Computer One", "No longer used", "Dual-core", '1GB');
  print(com1.name);
  print(com1.description);

  Computer com2 =
      Computer("Computer two", "No longer used", "Single-core", '512MB');
  print(com1 == com2);

  Computer com3 = const Computer(
      "Computer three", "No longer used", "Single-core", '256MB');
  Computer com4 = const Computer(
      "Computer three", "No longer used", "Single-core", '256MB');
  print(com3 == com4); // const로 생성하고 속성이 같다면 같은 객체이다.
}

// 결과
Computer One
No longer used
false
true

 

class PointW {
  final int _x, _y;
  int? z;
  late int s; // 생성자가 실행 된 이후에 결정되므로 늦은 초기화
  PointW(this._x, this._y, [this.z]) { // [] 에는 선택적 파라미터 선언
    s = _x + _y;
  }
}

 

class Hero {}

mixin Movable {
  void move();
}
mixin Drawable {
  void draw();
}

// Dart에서 상속은 1개의 클래스에서만 (다중 상속 X)
// 상속은 하나, 다중 상속 효과인 믹스인은 여러개 가능
class SuperHero extends Hero with Movable, Drawable {
  @override
  void draw() {}

  @override
  void move() {}
}

void main(List<String> args) {
  // 다형성 적용되어 여러 타입을 쓸 수 있다.
  SuperHero sh = SuperHero();
  Hero h = SuperHero();
  Movable mo = SuperHero();
  Drawable da = SuperHero();
}

 

class Ticket {
  int age;

  // factory constructor에서는 this에 접근할 수 없음
  // 새로운 인스턴스를 생성하는 것이 아니라 객체만 사용
  factory Ticket(int age) {
    if (age >= 18) {
      return AdultTicket(age);
    } else {
      return ChildTicket(age);
    }
  }

  Ticket._withAge(this.age);
}

class AdultTicket extends Ticket {
  AdultTicket(int age) : super._withAge(age);
}

class ChildTicket extends Ticket {
  ChildTicket(int age) : super._withAge(age);
}

void main() {
  Ticket t = Ticket(17);
  print("Is class of t is ChildTicket? ${t is ChildTicket}");
}

// 결과
Is class of t is ChildTicket? true

 

// singletone에서는 자식 클래스를 만들 수 없음
// (싱글톤을 extends 하는 건 안 됨, singletone에서 서브 클래스 생성하는 건 가능)
// Factory constructor must return an instance of the class or sub-class.
// You can’t use this keyword inside factory constructor.
// It can be named or unnamed and called like normal constructor.
// It can’t access instance members of the class.

class Logger {
  static final Logger _instance = Logger._constructor();
  static bool appStatus = false; // 클래스 멤버 접근 위해

  // private 생성자를 만들어서 public 자동 생성자를 방지
  // 초기화 바디가 필요하면 {} 넣고 ; 뺀다.
  Logger._constructor();

  factory Logger() {
    return _instance;
  }

  setStatus(bool s) {
    // 클래스 멤버 접근 위해
    Logger.appStatus = s;
  }

  bool get status {
    // 클래스 멤버 접근 위해
    return appStatus;
  }
}

class AnotherLogger {
  static AnotherLogger? _instance;
  // 자동 생성자 방지. factory 메서드에서 named 생성자 통해 인스턴스 생성
  AnotherLogger._constructor();

  // _instance가 null이면 private 생성자 호출
  // null이 아니면 그냥 _instance 리턴
  factory AnotherLogger() {
    return _instance ??= AnotherLogger._constructor();
  }
}

void main(List<String> args) {
  Logger l1 = Logger();
  l1.setStatus(true);
  print("l1 status: ${l1.status}");
  Logger l2 = Logger();
  print("l2 status: ${l2.status}");
  print('==============================');
  print("Is l1, l2 is equal? ${l1 == l2}");
  print('==============================');
  AnotherLogger al1 = AnotherLogger();
  AnotherLogger al2 = AnotherLogger();
  print("Is al1, al2 is equal? ${al1 == al2}");
}

// 결과
l1 status: true
l2 status: true
==============================
Is l1, l2 is equal? true
==============================
Is al1, al2 is equal? true

 

void main(List<String> args) {
  Student s1 = Student('jon', 16, 1000);
  print("Student name: ${s1.name}");
  Student s2 = Student.anotherConstructor1('kelly', 15, 1001);
  print("Student name: ${s2.name}");
  Student s3 = Student.anotherConstructor2('mike', 14, 1002);
  print("Student name: ${s3.name}");
}

// 여러 가지 형태의 생성자

class Student {
  String? name;
  int? age;
  int? rollID;

  Student(String name, int age, int rollID)
      : this.name = name,
        this.age = age,
        this.rollID = rollID;

  Student.anotherConstructor1(String name, int age, int rollID) {
    this.name = name;
    this.age = age;
    this.rollID = rollID;
  }

  Student.anotherConstructor2(this.name, this.age, this.rollID);
}

// 결과
Student name: jon
Student name: kelly
Student name: mike

 

// Remember that constructors are not inherited, which means that
// a superclass’s named constructor is not inherited by a subclass.
// If you want a subclass to be created with a named constructor defined
// in the superclass, you must implement that constructor in the subclass.

class Person {
  String? name;
  Person.fromString(this.name) {
    print("in Person");
  }
}

class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromString().
  // Warning: Arguments to the superclass constructor don’t have access to this. 
  // For example, arguments can call static methods but not instance methods.
  Employee.fromString(name) : super.fromString(name) {
    print("in Employee");
  }
}

void main(List<String> args) {
  var emp = Employee.fromString('jon');
  print(emp);
}

// 결과
in Person
in Employee
Instance of 'Employee'

 

// Real Life Example Of Named Constructor In Dart

import "dart:convert";

class Person {
  String? name;
  int? age;
  static int count = 0;

  Person(this.name, this.age) {
    count++;
  }

  Person.fromJson(Map<String, dynamic> json) {
    count++;
    name = json['name'];
    age = json['age'];
  }

  Person.fromJsonString(String jsonString) {
    count++;
    Map<String, dynamic> json = jsonDecode(jsonString);
    name = json['name'];
    age = json['age'];
  }

  get getCount => count;
}

void main(List<String> args) {
  String jsonString1 = '{"name": "John", "age": 25}';
  String jsonString2 = '{"name": "V", "age": 30}';

  Person p1 = Person.fromJsonString(jsonString1);
  print("Person #${p1.getCount} name: ${p1.name}");
  print("Person #${p1.getCount} age: ${p1.age}");

  Person p2 = Person.fromJsonString(jsonString2);
  print("Person #${p2.getCount} name: ${p2.name}");
  print("Person #${p2.getCount} age: ${p2.age}");
}

// 결과
Person #1 name: John
Person #1 age: 25
Person #2 name: V
Person #2 age: 30

 

// Constant Constructor In Dart
//
// Constant constructor is a constructor that creates a constant object.
// A constant object is an object whose value cannot be changed.
// A constant constructor is declared using the keyword const.
//
// Constant Constructor is used to create a object
// whose value cannot be changed. It Improves the performance of the program.
//
// Rule For Declaring Constant Constructor In Dart
// All properties of the class must be final.
// It does not have any body.
// Only class containing const constructor is initialized using the const keyword.

class Point {
  final int x;
  final int y;

  const Point(this.x, this.y);
}

void main(List<String> args) {
  Point p1 = const Point(1, 1);
  Point p2 = const Point(1, 1);

  print("Is p1, p2 equality: ${p1 == p2}");

  Point p3 = Point(2, 2);
  Point p4 = Point(2, 2);
  print("Is p3, p4 equality: ${p3 == p4}");
}

// 결과
Is p1, p2 equality: true
Is p3, p4 equality: false

 

// Encapsulation In Dart
//
// By default, every .dart file is a library.
// A library is a collection of functions and classes.
// A library can be imported into another library using the import keyword.

class NoteBook {
  final String _name;
  final double _price;

  NoteBook(this._name, this._price);

  // Getter In Dart With Data Validation
  String get name {
    if (_name == '') {
      return "no name";
    }
    return _name;
  }

  double get price => _price;
}

void main(List<String> args) {
  NoteBook nb1 = NoteBook('apple', 1000);
  print("First Notebook name: ${nb1.name}");
  print("First Notebook prize: ${nb1.price}");

  NoteBook nb2 = NoteBook('', 500);
  print("Second Notebook name: ${nb2.name}");
  print("Second Notebook prize: ${nb2.price}");
}

// 결과
First Notebook name: apple
First Notebook prize: 1000.0
Second Notebook name: no name
Second Notebook prize: 500.0

 

class Doctor {
  // private member
  final String _name;
  final int _age;
  final String _gender;

  // constructor
  Doctor(this._name, this._age, this._gender);

  // getters
  String get name => _name;
  int get age => _age;
  String get gender => _gender;

  // Map getter
  Map<String, dynamic> get map {
    return {"name": _name, "age": _age, "gender": _gender};
  }
}

void main(List<String> args) {
  // create an object of Doctor class
  Doctor d = Doctor("John", 41, "Male");
  print(d.map);
}

// 결과
{name: John, age: 41, gender: Male}

 

// Getter And Setter In Dart

class BankAccount {
  double _balance = 0;
  double get balance => _balance;

  void deposit(double amount) => _balance += amount;

  void withdraw(double amount) {
    if (_balance >= amount) {
      _balance -= amount;
    } else {
      throw Exception("Insufficient Balance");
    }
  }
}

void main(List<String> args) {
  BankAccount ba = BankAccount();
  ba.deposit(1000);
  print("Balance after deposit: ${ba.balance}");
  ba.withdraw(500);
  print("Balance after withdraw: ${ba.balance}");
}

// 결과
Balance after deposit: 1000.0
Balance after withdraw: 500.0

 

// Terminology
//
// Parent Class: The class whose properties and methods are
// inherited by another class is called parent class.
// It is also known as base class or super class.

// Child Class: The class that inherits the properties and
// methods of another class is called child class.
// It is also known as derived class or sub class.

// Types Of Inheritance In Dart
//
// Multiple Inheritance - In this type of inheritance,
// a class can inherit from multiple classes.
// Dart does not support multiple inheritance.
// For e.g. Class Toyota extends Car, Vehicle {} is not allowed in Dart.

// Key Points
//
// Inheritance is used to reuse the code.
// Inheritance is a concept which is achieved by using the extends keyword.
// Properties and methods of the super class can be accessed by the sub class.
// Class Dog extends class Animal{} means Dog is sub class and Animal is super class.
// The sub class can have its own properties and methods.

// Does Inheritance Finished If I Learned Extending Class?
// No, there is a lot more to learn about inheritance.
// You need to learn about Constructor Inheritance, Method Overriding,
// Abstract Class, Interface and Mixin etc.

// Inheritance Of Constructor In Dart
//
// The constructor of the parent class is called first
// and then the constructor of the child class is called.

// Accessing Super Properties In Dart
class Car {
  int numOfSeats = 4;
}

class Tesla extends Car {
  @override
  // ignore: overridden_fields
  int numOfSeats = 6;

  show() {
    print("No of seats in Tesla: $numOfSeats");
    print("No of seates in Car: ${super.numOfSeats}");
  }
}

class Employee {
  Employee.manager() {
    print("Employee named constructor.");
  }
}

class Manager extends Employee {
  Manager.manager() : super.manager() {
    print("Manager named constructor.");
  }
}

void main(List<String> args) {
  Tesla t = Tesla();
  t.show();

  print("==============================");

  Manager m = Manager.manager();
}

// 결과
No of seats in Tesla: 6
No of seates in Car: 4
==============================
Employee named constructor.
Manager named constructor.

 

// Super With Multilevel Inheritance In Dart

class Laptop {
  // parent method
  show() {
    print("Laptop shows.");
  }
}

class MacBook extends Laptop {
  // child method
  @override
  show() {
    print("MacBook shows.");
    super.show();
  }
}

class MacBookPro extends MacBook {
  // grandchild method
  @override
  show() {
    print("MacBookPro shows.");
    super.show();
  }
}

void main(List<String> args) {
  MacBookPro mbp = MacBookPro();
  mbp.show();
}

// 결과
MacBookPro shows.
MacBook shows.
Laptop shows.

 

// Polymorphism By Method Overriding In Dart

class Car {
  power() {
    print("It runs on petrol.");
  }
}

class Honda extends Car {}

class Tesla extends Car {
  @override
  power() {
    print("It runs on electricity.");
  }
}

void main(List<String> args) {
  Honda h = Honda();
  h.power();
  Tesla t = Tesla();
  t.power();
}

// 결과
It runs on petrol.
It runs on electricity.

 

// Dart Static Method
//
// A static method is shared by all instances of a class. 
// It is declared using the static keyword. 
// You can access a static method without creating an object of the class.

class SimpleIntrest {
  static double calculateInterest(double principle, double rate, double time) {
    return (principle * rate * time) / 100;
  }
}

void main(List<String> args) {
  print("The simple interest is ${SimpleIntrest.calculateInterest(1000, 2, 2)}");
}

// 결과
The simple interest is 40.0

 

// Static Method In Dart

import 'dart:math';

class PasswordGenerator {
  static String generateRandomPassword() {
    List allAlphabets = 'abcdefghijklmnopqrstuvwxyz'.split('');
    List numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
    List specialCharacters = ["@", "#", "%", "&", "*"];
    List password = [];
    for (int i = 0; i < 5; i++) {
      password.add(allAlphabets[Random().nextInt(allAlphabets.length)]);
      password.add(numbers[Random().nextInt(numbers.length)]);
      password.add(specialCharacters[Random().nextInt(specialCharacters.length)]);
    }
    return password.join();
  }
}

void main(List<String> args) {
  print(PasswordGenerator.generateRandomPassword());
}

// 결과
z2%d6*e1#a6#v5#

 

// Enum In Dart

enum Days { sunday, monday, tuesday, wednesday, thursday, friday, saturday }

void main(List<String> args) {
  var today = Days.friday;

  switch (today) {
    case Days.sunday:
      print("Today is Sunday.");
      break;
    case Days.monday:
      print("Today is Monday.");
      break;
    case Days.tuesday:
      print("Today is Tuesday.");
      break;
    case Days.wednesday:
      print("Today is Wednesday.");
    case Days.thursday:
      print("Today is Thursday.");
      break;
    case Days.friday:
      print("Today is Friday.");
      break;
    case Days.saturday:
      print("Today is Saturday.");
      break;
  }
}

// 결과
Today is Friday.

 

// Constructor In Abstract Class
//
// Key Points To Remember
//
// You can’t create an object of an abstract class.
// It can have both abstract and non-abstract methods.
// It is used to define the behavior of a class that other classes can inherit.
// Abstract method only has a signature and no implementation.

abstract class Bank {
  String name;
  double rate;

  Bank(this.name, this.rate);

  // abstract method
  interest();

  // non-abstract method: it have an implementation.
  show() {
    print('Bank name: $name');
  }
}

class JPM extends Bank {
  JPM(String name, double rate) : super(name, rate);

  @override
  interest() {
    print('The rate of interest of $name is $rate');
  }
}

class BOA extends Bank {
  BOA(String name, double rate) : super(name, rate);

  @override
  interest() {
    print('The rate of interest of $name is $rate');
  }
}

void main(List<String> args) {
  JPM jpm = JPM('JPM', 8.4);
  jpm.show();
  jpm.interest();

  BOA boa = BOA('BOA', 7.3);
  boa.show();
  boa.interest();
}

// 결과
Bank name: JPM
The rate of interest of JPM is 8.4
Bank name: BOA
The rate of interest of BOA is 7.3

 

// ignore_for_file: public_member_api_docs, sort_constructors_first
/*
Some concepts of Classes
  - used to define "new types"
  - Containers that hold some data
  - Functionality for manipulating that data
  - Basis of object-oriented programming
  - They can encapsulate the state of our programs
  - Class design is type design
  - Strive to make your types
    = easy to use correctly
    = hard to use incorrectly
*/

void main(List<String> args) {
  final ba = BankAccount(accountHolder: 'John', balance: 100);
  ba.deposit(100);
  ba.deposit(50);

  final success1 = ba.withdraw(100);
  print('success: $success1, balance: ${ba.balance}');
  final success2 = ba.withdraw(100);
  print('success: $success2, balance: ${ba.balance}');
}

class BankAccount {
  /*
    Member initialization:
      - via initializer list (more verbose)
      - with this. shorthand syntax (simpler, more often used)
      - sometimes initializer lists are still needed
  */
  double _balance;
  final String accountHolder;

  BankAccount({required this.accountHolder, double balance = 0})
      : _balance = balance;

  // use a private stored variable + a public getter variable
  double get balance => _balance;

  void deposit(double amount) {
    _balance += amount;
  }

  bool withdraw(double amount) {
    if (_balance > amount) {
      _balance -= amount;
      return true;
    } else {
      return false;
    }
  }
}

// 결과
success: true, balance: 150.0
success: true, balance: 50.0

 

void main(List<String> args) {
  var s = Student(
    title: 'high-school student',
    grade: 3,
    gender: 'male',
    age: 15,
  );

  print(s);
}

class Person {
  String gender;
  int age;

  Person({required this.gender, required this.age});
}

class Student extends Person {
  String title;
  int grade;

  Student({
    required this.title,
    required this.grade,
    required super.gender,
    required super.age,
  });

  @override
  String toString() {
    return 'Title: $title, Grade: $grade, Gender: $gender, Age: $age';
  }
}

// 결과
Title: high-school student, Grade: 3, Gender: male, Age: 15

 

void main(List<String> args) {
  Table t = Table(name: 'table', legs: 4, address: 'Seoul, KR');
  t.now();
  t.cleaning();
}

mixin TimeStamp {
  void now() {
    DateTime dt = DateTime.now();
    print(dt);
  }
}

class Home {
  String address;
  Home({required this.address});

  void show() {
    print('I am "$runtimeType" instance');
  }
}

abstract class Cleanable {
  void cleaning();
}

class Table extends Home with TimeStamp implements Cleanable {
  String name;
  int legs;
  Table({required this.name, required this.legs, required super.address});

  @override
  void show() {
    print('name: $name, legs: $legs');
  }

  @override
  void cleaning() {
    print('now $name is cleaning');
  }
}

class SimpleMattresses extends Home {
  String name;
  String style;
  SimpleMattresses(
      {required this.name, required this.style, required super.address});

  void folding() {
    print('folding');
  }

  @override
  void show() {
    print('name: $name, style: $style');
  }
}

/*
A class is a structure that defines the data and the methods to work on that data.

In other words, we can describe classes as a template to create a set of
objects that share common data and behavior.
*/

// 결과
2024-01-30 10:03:28.612122
now table is cleaning

 

void main(List<String> args) {}

class A {
  int x;
  int y;
  A({required this.x, required this.y});
}

class B {
  int z;
  B({required this.z});
}

class C implements A, B {
  @override
  int x;

  @override
  int y;

  @override
  int z;
  C({required this.x, required this.y, required this.z});
}

 

import 'strings.dart';

void main(List<String> args) {
  print(Strings.loading);
  print(Strings.doubleValue(10));
}


/*
use classes to define new types
weare used to int, double, String, bool,
List, Map, Set, Function
classes - blueprint for objects
object - containewr that holds some data (functionality
to manipulate the data)


*/


// strings.dart

class Strings {
  static String loading = 'Busy loading... please wait';
  static String errorUsername = 'The username you typed does not exist';
  static String errorPassword = 'The password you typed is not correct';

  static int doubleValue(int value) => value * 2;
}

// 결과
Busy loading... please wait
20

 

// ignore_for_file: public_member_api_docs, sort_constructors_first, hash_and_equals
void main(List<String> args) {
  var p1 = Person(name: 'John', age: 22);
  var p2 = Person(name: 'John', age: 22);

  print(p1 == p2);

  var p3 = Person(name: 'John', age: 23);
  print(p1 == p3);

  print(p3);
}

class Person {
  String name;
  int age;

  Person({
    required this.name,
    required this.age,
  });

  @override
  String toString() {
    return 'Person name: $name, age: $age';
  }

  @override
  bool operator ==(Object obj) {
    if (obj is Person) {
      if (name == obj.name && age == obj.age) {
        return true;
      }
    }

    return false;
  }
}

// 결과
true
false
Person name: John, age: 23

 

void main(List<String> args) {
  PrintItems<String> str = PrintItems(times: 3, printedItem: 'Hi');
  str.printItem();

  PrintItems<double> d = PrintItems(times: 2, printedItem: 10.2);
  d.printItem();

  PrintItems<PrintItems> recur = PrintItems(times: 1, printedItem: str);
  recur.printItem();
}

class PrintItems<T> {
  int times;
  T printedItem;

  PrintItems({
    required this.times,
    required this.printedItem,
  });

  void printItem() {
    for (int i = 0; i < times; i++) {
      print(printedItem);
    }
  }
}

// 결과
Hi
Hi
Hi
10.2
10.2
Instance of 'PrintItems<String>'
반응형

관련글 더보기

댓글 영역