JiSoo's Devlog
[Dart 시작하기] Section 4 본문
class에서 property를 선언할 때는 타입을 사용해 정의한다
function 내에서 변수 사용 시 var 사용하면 된다
class 내부에는 타입 반드시 선언
class Player {
String name = 'jisoo';
int xp = 1500;
}
void main(){
var player = Player(); // Player 인스턴스 생성
print(player.name);
player.name = 'lala';
print(player.name);
}
Player 인스턴스 생성 후 property의 값을 바꿀 수도 있고 원하는 값을 가져올 수도 있다
만약 name을 바꾸지 못하게 하고 싶다면 final 추가
class Player {
final String name = 'jisoo';
int xp = 1500;
}
class method 내에서의 this는 사용하기 않는 것이 권고되고 있다
class Player {
final String name = 'jisoo';
int xp = 1500;
void sayHello() {
print("Hi my name is $name");
}
}
void main() {
var player = Player();
}
method 내에도 name이라는 변수가 있다면 이 경우에 name에 접근할 때는 this.name을 써야 한다
class Player {
final String name='jisoo';
int xp = 1300;
void sayHello(){
var name = 'nico';
print("Hello ${this.name}");
}
}
그런 게 아니라면 this 없이 name만 써줘도 된다
위처럼 실행하면 "Hello jisoo"로 나온다
인자로 이름과 xp를 전달해 새로운 player 만들려면 constructor(생성자) 사용
constructor method의 이름은 class의 이름과 같아야 한다
late는 변수들의 값을 나중에 받아올 거라는 것을 의미하는데 class에서 유용하다
class Player {
late final String name;
late int xp;
Player(String name, int xp){
this.name = name;
this.xp = xp;
}
void sayHello() {
print("Hi my name is $name");
}
}
void main() {
var player = Player("jisoo", 1500);
player.sayHello();
var player2 = Player("min", 2500);
player2.sayHello();
}
Player(this.name, this.xp);
↑ position parameters(argument)
이렇게 줄일 수 있는데 첫 번째 인자는 첫 번째 자리인 this.name으로 가고 두 번째 인자는 두 번째 자리인 this.xp로 간다
너무 많은 positional argument가 서로 이웃해 있으면 혼란스러워진다
named argument를 가진 constructor로 바꾸려면 타입 선언하고 required로 만들기
class Player {
final String name;
int xp;
String team;
int age;
Player( // named constructor parameter
{required this.name,
required this.xp,
required this.team,
required this.age});
void sayHello() {
print("Hi my name is $name");
}
}
void main() {
var player = Player(
name: "jisoo",
xp: 1200,
team: 'blue',
age: 21,
);
player.sayHello();
var player2 = Player(
name: "min",
xp: 2500,
team: 'blue',
age: 12,
);
player2.sayHello();
}
이 방법을 사용하면 데이터가 많은 클래스들을 만들 때도 인자들의 위치를 기억하지 않아도 되고 각각을 key와 value 쌍으로 작성하기만 하면 된다
named constructors ↓
class Player {
final String name;
int xp, age;
String team;
Player(
{required this.name,
required this.xp,
required this.team,
required this.age});
Player.createBluePlayer({required String name, required int age})
: this.age = age,
this.name = name,
this.team = 'blue',
this.xp = 0;
void sayHello() {
print("Hi my name is $name");
}
}
void main() {
var player = Player.createBluePlayer(
name: "jisoo",
age: 21,
);
}
여기서 콜론(:)을 넣음으로써 Player 객체를 초기화하겠다고 하는 것뿐!
positional syntax ↓
class Player {
final String name;
int xp, age;
String team;
Player(
{required this.name,
required this.xp,
required this.team,
required this.age});
Player.createRedPlayer(String name, int age)
: this.age = age,
this.name = name,
this.team = 'red',
this.xp = 0;
void sayHello() {
print("Hi my name is $name");
}
}
void main() {
var redPlayer = Player.createRedPlayer("jisoo", 21);
}
: 콜론을 사용하는데 이것은 Player 객체를 초기화한다
기본적으로 모든 positional parameter는 required이다
named parameter에는 기본적으로 required 속성이 없다
Player 클래스의 생성과 초기화 작업 ↓
class Player {
final String name;
int xp;
String team;
Player.fromJson(Map<String, dynamic> playerJson) :
name = playerJson['name'],
xp = playerJson['xp'],
team = playerJson['team'];
class 내부의 name을 playerJson Map에서 key가 name인 값을 가져와 넣고 xp에도 key가 xp인 값을 가져와 넣는 방식
class Player {
final String name;
int xp;
String team;
Player.fromJson(Map<String, dynamic> playerJson)
: name = playerJson['name'],
xp = playerJson['xp'],
team = playerJson['team'];
void sayHello() {
print("Hi my name is $name");
}
}
void main() {
var apiData = [
{
"name": "jisoo",
"team": "red",
"xp": 0,
},
{
"name": "lynn",
"team": "red",
"xp": 0,
},
{
"name": "dal",
"team": "red",
"xp": 0,
}
];
apiData.forEach((playerJson) {
var player = Player.fromJson(playerJson);
player.sayHello();
});
}
{ }는 named parameters를 사용할 때 필요 (name: "", age:1, good:true)
( )는 positional parameters를 사용할 때 필요 ("", 1, true)
Cascade operator
세미콜론 지우고 마지막 부분에만 써주기
void main() {
var jisoo = Player(name: 'jisoo', xp: 1200, team: 'red')
..name = 'las'
..xp = 120000
..team = 'blue';
}
↕ 둘이 같은 코드
void main() {
var jisoo = Player(name: 'jisoo', xp: 1200, team: 'red');
jisoo.name = 'las';
jisoo.xp = 120000;
jisoo.team = 'blue';
}
void main() {
var jisoo = Player(name: 'jisoo', xp: 1200, team: 'red');
var potato = jisoo
..name = 'las'
..xp = 120000
..team = 'blue'
..sayHello();
}
Enums은 우리가 실수하지 않게 도와주는 타입
텍스트 형태로 적지 않아도 된
enum Team { red, blue }
enum XPLevel {beginner, medium, pro}
class Player {
String name;
XPLevel xp;
Team team;
Player({required this.name, required this.xp, required this.team})
void sayHello() {
print("Hi my name is $name");
}
}
void main() {
var jisoo = Player(name: 'jisoo', xp: XPLevel.medium, team: Team.red);
var potato = jisoo
..name = 'las'
..xp = XPLevel.pro
..team = Team.blue
..sayHello();
}
추상화 클래스로 객체를 생성할 수 없다
추상화 클래스는 다른 클래스들이 직접 구현해야 하는 메서드들을 모아 놓은 일종의 청사진이라 보면 된다
수많은 청사진에 메서드의 이름과 반환 타입만 정해서 정의할 수 있다
추상 클래스는 특정 메서드를 구현하도록 강제한다
추상화 클래스는 이를 상속받는 모든 클래스가 가지고 있어야 하는 메소드를 정의하고 있다
abstract class Human {
void walk();
}
enum Team { red, blue}
enum XPLevel {beginner, medium, pro}
class Player extends Human {
String name;
XPLevel xp;
Team team;
Player({required this.name, required this.xp, required this.team})
void walk(){
print("i'm walking");
}
void sayHello() {
print("Hi my name is $name");
}
}
class Coach extends Human {
void walk(){
print('the couch is walking');
}
}
super 키워드를 통해 (확장한) 부모 클래스와 상호작용할 수 있게 해 준다
Player 생성자 함수에 있는 name을 위에 있는 Human으로 전달
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;
Player({
required this.team,
required String name,
}) : super(name: name);
@override
void sayHello(){
super.sayHello();
print('and I play for ${team}');
}
}
void main() {
var player = Player(team: Team.red, name:'jisoo', );
player.sayHello();
}
class Human {
final String name;
Human(this.name);
void sayHello() {
print("Hi my name is $name");
}
}
enum Team { blue, red }
class Player extends Human {
final Team team;
Player({
required this.team,
required String name,
}) : super(name);
@override
void sayHello(){
super.sayHello();
print('and I play for ${team}');
}
}
void main() {
var player = Player(team: Team.red, name:'jisoo', );
player.sayHello();
}
super에 name을 전달해 주면 이 클래스를 전달한 name과 함께 호출하게 되는 것
@override를 이용해 부모 클래스의 객체를 받아올 수 있다
super은 확장한 부모 클래스의 프로퍼티에 접근하게 하거나 메소드를 호출할 수 있게 해 준다
Mixin은 생성자가 없는 클래스를 의미
mixin Strong {
final double strenghtLevel = 1500.99;
}
mixin QuickRunner {
void runQuick() {
print("ruuuuuuuun!");
}
}
mixin Tall {
final double height = 1.99;
}
enum Team { blue, red }
class Player with Strong, QuickRunner, Tall {
final Team team;
Player({
required this.team,
required String name,
});
}
class Horse with Strong, QuickRunner {}
class Kid with QuickRunner {}
void main() {
var player = Player(
team: Team.red,
name: 'jisoo',
);
player.runQuick();
}
Mixin 클래스들을 하나의 클래스에 단 한 번만 사용할 것 같으면 의미가 없다
Mixin의 핵심은 여러 클래스에 재사용이 가능하다는 점
with는 extend와 다르다! extend를 하게 되면 확장한 그 클래스는 부모 클래스가 되고 자식 클래스는 부모 클래스를 super로 접근할 수 있다
Mixin은 with라는 키워드를 사용하고 그 역할은 단순히 Mixin 내부의 프로퍼티와 메소드들을 가져오는 것뿐 부모 클래스가 되거나 하지는 않는다
** class Strong , class QuickRunner 이런 식으로 적으니까 오류가 나서 mixin Strong 혹은 mixin class Strong으로 적어야 한다
'App > Dart' 카테고리의 다른 글
[Dart 시작하기] Section 3 (0) | 2024.01.24 |
---|---|
[Dart 시작하기] Section 2 (0) | 2024.01.16 |
[Dart 시작하기] Section 1 (0) | 2024.01.16 |