flutter

dart

paulaner80 2019. 4. 3. 16:40
반응형

as

as와 is, is!은 type test operator 들이다.

  

as 형변환..업캐스팅 다운캐스팅 쓸 수 있지만 다운케스팅이 확실히 가능할 때 사용하라고 함.




const와 final 차이

const는 실행 시에 결정되는 값은 할당 할 수 없다.



enum


enum ThemeColor { red, green, blue, orange }

void main(List<String> args) {
  //사용법
  ThemeColor temp = ThemeColor.blue;
  print(temp); //ThemeColor.blue
  print(temp.index); //2

  //각 이넘들은 0부터 시작하는 index 게터(getter)를 갖습니다.
  print(ThemeColor.red.index); //0
  print(ThemeColor.green.index); //1
  print(ThemeColor.blue.index); //2
  print(ThemeColor.orange.index); //3

  //전체 리스트의 내용을 가져오기...
  List<ThemeColor> themes = ThemeColor.values;
  print(themes); //[ThemeColor.red, ThemeColor.green, ThemeColor.blue, ThemeColor.orange]

  //숫자로 이넘값 얻어오기...
  print(ThemeColor.values[0]); //ThemeColor.red
  print(ThemeColor.values[1]); //ThemeColor.green
  print(ThemeColor.values[2]); //ThemeColor.blue
  print(ThemeColor.values[3]); //ThemeColor.orange
  //print(ThemeColor.values[4]); //RangeError (index): Invalid value: Not in inclusive range 0..3: 4
}




타입검사

 is 키워드



fat arrow syntax



함수

옵셔널 파라미터

옵셔널 파라미터는

네임드파라미터와, 포지셔널 파라미터가 있습니다.


1. 옵셔널 네임드 파라미터(Optional named parameters)

const Scrollbar({Key key, @required Widget child})


2. 옵셔널 포지셔널 파미터(Optional positional paraeters)

[] 로 쌓인 파라미터의 집합들

void main() {
printAlpabet("AAA"); //에러안남
printAlpabet("AAA", "BBB"); //에러안남
printAlpabet("AAA", "BBB", "CCC");
}

void printAlpabet(String name1, [String name2, String name3]) {
print("$name1 - $name2 - $name3");
}

/*
[결과]
AAA - null - null
AAA - BBB - null
AAA - BBB - CCC
*/


다른예제

Stream.periodic



3. 파라미터 기본값

 =를 사용하여 파라미터의 기본값을 지정할 수있다. ( todo: 문서에는 네임드 파라미터의 기본값을 지정할 수있다고하는데, 그냥 파라미터도 지정할 수 있는지알아보자. ) 만약 기본값이 없다면 null 입니다. 오래된 코드는  = 대신 :를 사용했을 수도 있습다. 본래에는 : 만 지원되었기 때문이다. 이것은 deprecate되었으므로 =를 사용하여 기본값을 지정하는게 좋습니다.


dart:core library에 Duration 클래스

Duration({int days: 0, int hours: 0, int minutes: 0, int seconds: 0, int milliseconds: 0, int microseconds: 0 })



클래스

생성자


common form


class Point {
num x, y;

Point(num x, num y) {
// There's a better way to do this, stay tuned.
this.x = x;
this.y = y;
}
}



syntatic sugar

생성자가 실행전에 x와 y가 세팅된다.

class Point {
num x, y;

// Syntactic sugar for setting x and y
// before the constructor body runs.
Point(this.x, this.y);

// Point(this.x, this.y) {
// print(this.x);
// print(this.y);
// }
}


default constructor

매개변수가 없고, 슈퍼클래스의 디폴트 생성자를 호출한다.


named constructor

생성자의 이름을 따로 지정할 수 있다. 용도를 명확히 하려고 할 때 사용하면 좋다.

생성자는 상속되지 않으므로 named constructor도 상속되지 않습니다.

class Point {
num x, y;

Point(this.x, this.y);

// Named constructor
Point.origin() {
x = 0;
y = 0;
}
}


슈퍼클래스의 비기본 생성자 호출하기

기본적으로 서브클래스의 생성자는 슈퍼클래스의 이름없고 매개변수가 없는 생성자를 호출합니다. 슈퍼클래스의 생성자는 생성자자의 본문이 시작하기전에 호출됩니다. 만약 이니셜라이즈 리스트를 사용하고 있다면  이니셜라이즈 리스트가 호출된 슈퍼클래스보다 먼저 실행됩니다.


실행순서

1. 이니셜라이져 리스트 (Initializer list)

2. 슈퍼클래스의 매개변수 없는 생성자

3. 서브클래스의 매개변수 없는 생성자

슈퍼클래스에 이름없고 매개션수 없는 생성자가 없다면, 서브클래스에서 슈퍼클래스의 생성자를 수동으로 반드시 호출해주어야합니다. 

class Person {
String firstName;

Person.fromJson(Map data) {
print('in Person');
}
}

class Employee extends Person {
// Person does not have a default constructor;
// you must call super.fromJson(data).
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}


슈퍼클래스 생성자의 매개변수는 생성자가호출되기전에 평가되므로 매개변수에 함수호출 같은 것을 할 수 있습니다.

class Employee extends Person {
Employee() : super.fromJson(getDefaultData());
// ···
}


이니셜라이져 리스트(Initilizer list)

1. 생성자 본문이 실행되기전에 인스턴스변수를 초기화 할 수 있습니다. :(콜론)으로 이니셜라이즈를 구분하세요

class Point {
num x, y;

Point(this.x, this.y);

// Named constructor
Point.origin() {
x = 0;
y = 0;
}

// 초기화 목록 Initializer list sets instance variables before
// the constructor body runs.
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}
}

main(List<String> args) {
Point p = Point.fromJson({"x": 10, "y": 20});
}


출력

In Point.fromJson(): (10, 20) 


2. 개발중이면 이니셜라이즈 리스트에 assert 처럼 유효성 검사를 할 수도 있습니다.


Point.withAssert(this.x, this.y) : assert(x >= 0) {
print('In Point.withAssert(): ($x, $y)');
}






생성자 리디렉션

특정 생성자에게 처리를 위임할 수 있다.

class Point {
num x, y;

// The main constructor for this class.
Point(this.x, this.y);

// Delegates to the main constructor.
Point.alongXAxis(num x) : this(x, 0);
}



예제 2

class Record {
final String name;
final int votes;
final DocumentReference reference;

Record.fromMap(Map<String, dynamic> map, {this.reference})
: assert(map["name"] != null),
assert(map["votes"] != null),
name = map["name"],
votes = map["votes"];

Record.fromSnapshot(DocumentSnapshot snapshot)
: this.fromMap(snapshot.data, reference: snapshot.reference);
}



상수생성자

1. 생성자를 const 로 선언 + 인스턴스 값들을 final로 선언

class ImmutablePoint {
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);

final num x, y;

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



2. 상수 생성자는 항상 상수를 생성하지는 않습니다.


class Point {
num x, y;
Point(this.x, this.y);
}

class ImmutablePoint {
final num x, y;
const ImmutablePoint(this.x, this.y);
}

main(List<String> args) {
var ia = const ImmutablePoint(1, 1);
var ib = const ImmutablePoint(1, 1);

//var ma = const Point(1, 1); //컴파일 에러
var ma = Point(1, 1);
var mb = Point(1, 1);

print(identical(ia, ib)); // 결과 : true, They are the same instance!
print(identical(ma, mb)); // 결과 : false,
}



팩토리 생성자

항상 새로운 객체를 만들 필요가 없는 경우 factory 키워드를 사용하세요. 팩토리 생성자는 캐쉬에 있는 객체를 리턴해줍니다. 


class Logger {
final String name;
bool mute = false;

// _cache is library-private, thanks to
// the _ in front of its name.
static final Map<String, Logger> _cache = <String, Logger>{};

factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}

Logger._internal(this.name);

void log(String msg) {
if (!mute) print(msg);
}
}


팩토리 생성사 사용예 : 싱글톤

class MyClass {
//멤버는 팩토리 생성자에서 접근할 수 없으므로 static 키워드를 붙여 준다.
static final MyClass _singleton = new MyClass._internal();

//factory 키워드는 생성자가 리턴을 할 수 있도록 해준다.
factory MyClass() {
return _singleton;
}

MyClass._internal() {}
}

main(List<String> args) {
MyClass myObj1 = MyClass();
MyClass myObj2 = MyClass();
print(identical(myObj1, myObj2)); //결과 true
}


선택적인 매개변수

함수를 만들 때 매개변수가 선택적일 수 있다.



생성자 - Named Constructor

  생성자의 이름을 따로 지정할 수도 있다.


생성자 - Getter / Setter

   getter, setter 메서드를 언어 차원에서 지원을 한다. get과 set이라는 키워드가 있다.





Implicit interfaces

  https://www.dartlang.org/guides/language/language-tour#implicit-interfaces

  Dart에선 모든 클래스가 implicit 하게 인터페이스로 취급되기 때문에 어떤 클래스를 상속하지 않고 그 클래스의 메서드나 변수를 사용하고 싶다면 간단하게 implements하면 된다.

  물론 abstract class로 생성한다음 implements 할수도 있다.


class Person {
final _name;
Person(this._name);
String greet(String who) => 'Hello, $who i am $_name';
}

class Impostor implements Person {
@override
// TODO: implement _name
get _name => null;

@override
String greet(String who) {
// TODO: implement greet
return null;
}
}


noSuchMethod



collection if



collection for



mixin

  여러개의 클래스 속성을 사용할 수 있는 개념이다. 하지만 상속을 해야 한다는 조건이 있으므로 그냥 사용하기 위해선 Object 클래스를 상속하면 된다. with라는 키워드를 통해 사용한다.

  인터페이스를 implements 할 경우 인터페이스에 있는 메서드를 구현해야 하지만 mixin을 쓰면 단지 해당 클래스가 가진 메서드와 변수를 공유하는 것이다. 또한 인터페이스를 implements 할 경우 해당 클래스의 객체 한 개만 생성하지만 mixin을 쓸 경우 해당 클래스의 객체와 mixin 되는 객체가 전부 생성된다.

  https://stackoverflow.com/questions/45901297/when-to-use-mixins-and-when-to-use-interfaces-in-dart/45903671#45903671

'flutter' 카테고리의 다른 글

플러터용 파이어 베이스 1부  (0) 2019.04.11
Dart에서 stream 만들기  (0) 2019.04.04
Dart mixin 이란?  (0) 2019.04.03
RxDart 관련 내용들  (0) 2019.03.29
Dart mxins  (0) 2019.03.27