lan/dart

[Dart] 4. 클래스 생성자(Constructor)

캄춰 2023. 12. 6. 14:08
728x90
반응형

클래스는 앞에 클래스를 명시해주고 뒤에 클래스명을 기입

class Player {
}

 

 

일반적인 클래스 생성 문법

: var player = Player();

: 프로퍼티 값은 초기화된 상태여야 함

class Player {
    // class내부에서는 타입을 꼭 명시해주어야 함
    String name = 'neander';
    int xp = 1500;

    // name은 현재 바꿀 수 있는데 바꾸고 싶지 않은 경우
    final name1 = ''

    // class method에서는 this.name이렇게 'this' 사용하는 것을 권장하지 않는다
    void sayHello() {
        print("Hi my name is $name")
    }
}
void main() {
    var player = Player();  // 앞에 new를 붙일 필요 없다(붙여도 상관없다)
    print(player.name);
    player.name = 'lalala';
    print(player.name);     // changed
}

 

 

 

Positional Arguments

: 순서대로 파라메터 값을 기입해야한다.

: 프로퍼티 값은 나중에 초기화 되기 떄문에 'late'를 사용한다.

: 클래스 내에서 this는 권장하지 않지만, 사용해도 무방하다.

// late를 사용해서 property들을 대기 시킨다.
// class에 parameter arguments넣기
class Player {
    late final String name;
    late int xp;

    // constructor: 전형적인 방법이지만... Dart에서는 더욱 간단한 constructor가 있다.
    Player(String name, int xp) {
        this.name = name;
        this.xp = xp;
    }

    void sayHello() {
        print("Hi my name is $name");
    }
}

 

 

: this.name = name; 이렇게 명시적 초기화를 할 수 있지만,

: 생성자 파라메터 내에서 선언 해주어 더욱 간결하게 만들 수 있다.

// dart에서 더욱 간단한 constructor 만드는 것
// late를 사용하지 않고 property들에게 바로 init을 시켜줄 수 있다.
class Player {
    final String name;
    int xp;

    // 파라메터의 property값을 넣어주면 외부에서 해당 위치에 선언시
    // 바로 적용이 된다.    positional arguments 값을 넣는 위치가 중요하다.
    Player(this.name, this.xp);

    void sayHello() {
        print("Hi, my name is $name");
    }
}

 

void main() {
    var player = Player('neander', 30);
    player.sayHello();
}

 

 

Named Arguments

: 일반 함수에 명시 해주는 것처럼 '중괄호'를 사용한다.

: 생성자에 블럭으로 처리하지 않고 ':' 뒤에 콜론을 사용하여 표현할 수 있다.(훨씬 명료해보임, 끝에 ';' 세미콜론으로 마무리)

// positional arguments가 많아지면 헷갈려 진다.
class Player {
    // {} 중괄호로 감싸주면 된다.
    final String name;
    int xp;

    Player({this.name, this.x});    // 하지만 이렇게 하면 null safety로 인해 null체크를 해주어야 한다.
    Player({required this.name, required this.xp});  // required를 넣어주어야 한다.
}

 

다르게 constructor을 생성하는 방법

class Player {
    final String name, team;
    int xp, age;

    // 블루팀이지만 값은 '0'인 생성자
    // Dart 고유 특징.. ':' 생성자 맨 뒤에 콜론':'만을 사용한다
    // 그리고 끝에 ';'세미콜론으로 끝내준다.
    Player.createBluePlayer({required String name, required int age}) :
        this.age = age,
        this.name = name,
        this.team = 'blue',
        this.xp = 0;

    // no named parameter
    Player.createRedPlayer(String name, int age) : 
        this.age = age,
        this.name = name,
        this.team = 'red',
        this.xp = 0;
}

 

 

constructor응용

: Map을 사용해서 값을 넣고, 해당 값이 잘 표출되는지 확인

void main() {
    var apiData = [
        {
            "name":"neander",
            'team': 'red',
            'xp': 0
        }, 
        {
            "name":"hong",
            'team': 'red',
            'xp': 0
        },
        {
            "name":"kk",
            'team': 'red',
            'xp': 0
        }
    ];

    apiData.forEach((playerJson) {
        var player = Player.fromJson(playerJson);
        player.sayHello();
    });
}
// 위의 값들을 Player class로 묶어줄 것

class Player {
    final String name;
    int xp;
    String team;

    // ':' immediately init
    Player.fromJson(Map<String, dynamic> playerJson) :
        name = playerJson['name'],
        xp = playerJson['xp'],
        team = playerJson['team'];

    void sayHello() {
        print("Hi, my name is $name");
    }
}

 

 

 

Cascade Operator

: kotlin의 scope function과 유사하다.

: 코드 수정을 상당히 간결하게 해주고, 인스턴스를 연속해서 호출하지 않기 때문에 매우 간결하고 눈이 편안하다..^^

: 객체 뒤에 ' .. ' 을 사용한다. 쩜쩜~ 그리고 해당 객체의 프로퍼티, 함수를 호출하여 사용한다.

class Player {
    final String name;
    int xp;
    String team;

    Player({
        required this.name,
        required this.xp,
        required this.team
    });

    void sayHello() {}
}

 

// 위와 같은 경우 생성했을 때 더욱 명료하게 코드를 작성할 수 있음
// Cascade operator
void main() {
    var player = Player(name: 'neander', xp: 30, team: 'red');
    // player 생성자를 만든 다음, 값을 수정하고 싶은 경우
    player.name = 'kk';
    player.xp = 26;
    player.team = 'green';  // 이렇게 바꿔주어야 한다.

    // 하지만 dart에서는 kotlin의 scope function처럼 앞의 'player'를 연속적으로 사용하지 않는 문법이 있다.
    // ..은 player1을 가르킨다.
    var player1 = Player(name: 'hong', xp: 32, team: 'yellow')
        ..name = 'zz';
        ..xp = 1400;
        ..team = 'blue';

    // 생성자를 만든 뒤에도 사용할 수 있다.
    // 그리고 갖고 있던 함수도 사용할 수 있다.
    var player2 = Player(name: 'greenman', xp:58, team: 'fall');
    var bluo = player2
        ..name = 'yy'
        ..xp = 54
        ..sayHello();
}

 

 

enum class

: 개발자들이 실수하지 않도록 도와줌

: 오타를 줄일 수 있다

: enum 클래스명

enum Team {
    red,
    blue
}   // red, blue라는 새로운 타입을 만든 것

class Player {
    final String name;
    int xp;
    Team team;      // Team이라는 enum class로 훨씬더 안전하게 만듦, 오타를 줄일 수 있지~~

    Player({
        required this.name,
        required this.xp,
        required this.team
    })
}

void main() {
    // Team.blue라는 enum class로 명확하게 명시를 해줄 수 있어서 안전하고 좋다.
    var player = Player(name: 'neander', xp: 30, team: Team.blue);
}

 

 

 

abstract class, 추상 클래스

: 추상 클래스는 설계 도면이라고 생각하면 된다.

: 추상 클래스를 보고서 클래스를 만드는 느낌

: 그래서 꼭 필요한 프로퍼티나 함수를 잊지 않고 재정의 할 수 있다.

// 추상화는 클래스를 생성할 수 없고
// 다른 클래스들이 직접 구현 해야하는 메서드들 모아 놓음
abstract class Human {
    void walk();
}

// 그럼 Human이라는 설계도를 extends한 클래스는 Human 추상화 클래스가 갖고 있던
// 프로퍼티, 함수들을 모두 내려 받아서 재정의하여 사용해야 한다.
class Player extends Human {
    void walk() {
        print('Im walking');
    }
}

class Coach extends Human {
    void walk() {
        print('the coach is walking');
    }
}

 

 

 

상속, extends

: 상속하는 클래스를 그대로 가져다 사용할 수 있다.

: 흔히 부모라고 하고, 그 부모에서 허용하는 범위내 프로퍼티, 함수 모두 사용할 수 있다.

: 부모에 접근하려면 'super'를 사용하여 접근하고

: 부모 생성자도 선언해야 하므로 본인 생성자 뒤에 콜론 ':' 을 붙이고 super를 사용하여

: 부모 생성자도 생성해준다.

// extends 
class Human {
    final String name;

    Human({required this.name});

    void sayHello() {
        print("Hi, my name is $name");
    }
}

enum Team {
    blue,
    red
}

class Player extends Human {
    final Team team;

    // Human의 생성자도 생성해주어야 한다.
    // 콜론을 사용하고 super 사용
    Player({
        required this.team,
        required String name 
    }) : super(name: name);

    // Human의 함수를 재정의하고 싶은 겨웅
    @override
    void sayHello() {
 
    }
}

// super는 부모 클래에 접근할 수 있게 해준다.
void main() {
    var player = Player(team: Team.red, name: 'neander');
    player.team = Team.red
}

 

 

Mixin class, 생성자가 없는 클래스

: Mixin class의 조건은 클래스 내부에 생성자가 없어야 한다.

: Mixin class역할은 해당 클래스의 설정 값을 사용하는 것,

: 사용할 클래스에서 extends가 아닌 'with'를 사용

// 부모 클래스가 아닌 내부 내용을 뺏어오는 것이다.
// Mixin의 조건은 생성자가 없어야한다. **
class Strong {
    final double strengthLevel = 1500.99;
}

class QuickRunner {
    void runQuick() {
        print("run!!!");
    }
}

class Tall {
    final double height = 1.99;
}

// 모든 클래스를 다 긇어온다.
class Player with Strong, QuickRUnner, Tall {

}

void main() {
    var player = Player();
    player.runQuick();  // 사용이 가능하다.
}

 

 

니콜라스(노마더 코드) 최고

728x90
반응형

'lan > dart' 카테고리의 다른 글

[Dart] Dart SDK 위치  (0) 2023.12.13
[Dart] StringBuffer : like java's StringBuilder  (0) 2023.12.08
[Dart] 3. 함수 사용(Function)  (0) 2023.12.05
[Dart] 2. Data Types  (0) 2023.12.05
[Dart] 1. Dart 언어시작  (0) 2023.12.05