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>'
댓글 영역