[Flutter] Class Constructor Parameters(named, optional, default)

keemeesuu·2022년 12월 1일
3

Flutter > Dart

목록 보기
4/4

Class 에서 사용되는 parameter(and argument) 그리고 Immutable Programing 정리

🚈 Parameters

🚗 기본 구조

void main() {
  Person person = Person("홍길동", 20);

  person.sayHello();
}

class Person {
  String name;
  int age;

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

  // 약식 표현. Flutter, Dart에서는 약식 표현을 권장한다.
  // Person(this.name, this.age);

  void sayHello() {
    print("Hello my name is $name , I'm $age years old");
  }
}

여기서 사용된 :(콜론)은 클래스를 초기화 하겠다고 선언하는 것.
즉, name과 age 변수를 초기화한다.


🚗 named parameter

파라미터를 중괄호({})로 감싸면 named parameter가 되어 이름으로 파라미터를 전달할 수 있다.

named parameter를 사용하기 위해서는

  • parameter는 중괄호({})를 사용하며 required(필수)을 인자 앞에 배치한다.

    	`@required` 는 필수로 입력해야 하는 값이면 입력하지 않으면 컴파일 되지 않는다.
    	`{}`와 `@required` 는 독립적인 존재이다.
  • argument는 인자: 값 으로 호출한다.


void main() {
  Person person = Person(name: "홍길동", age: 20);

  person.sayHello();
}

class Person {
  String name;
  int age;

  // named constructor parameter
  Person({required String name, required int age})
      : this.name = name,
        this.age = age;

  // named constructor parameter 약식 표현, Dart에서는 약식 표현을 권장한다.
  // Person({required this.name, required this.age});

  void sayHello() {
    print("Hello my name is $name , I'm $age years old");
  }
}

🚗 optional parameter

파라미터를 대괄호([])로 감싸면 선택형 인자를 설정할 수 있다.
선택사항이기 때문에 이름 없이 호출할 수도 있다.

void main() {
  Person hong = Person("홍길동");
  hong.sayHello();
  // 나이는 비밀.

  Person naruto = Person("나루토", 20);
  naruto.sayHello();
  // 제 나이는 20.
}

class Person {
  String name;
  int? age;

  Person(String name, [int? age])
      : this.name = name,
        this.age = age;

  // 약식 표현. Flutter, Dart에서는 약식 표현을 권장한다.
  // Person(this.name, [this.age]);

  void sayHello() {
    // print("Hello my name is $name ,I'm $age years old.");
    age is int ? print("제 나이는 $age.") : print("나이는 비밀.");
  }
}
  1. 변수 타입에 ?를 붙인다.
  2. constructor parameter에 [this.인자]로 감싼다.

🚗 default parameter

parameter의 기본값을 설정할 수 있다.

void main() {
  Person hong = Person("홍길동");
  hong.sayHello();
  // Hello my name is 홍길동 ,I'm 30 years old.

  Person naruto = Person("나루토", 20);
  naruto.sayHello();
  // Hello my name is 나루토 ,I'm 20 years old.
}

class Person {
  String name;
  int? age;

  Person(String name, [int? age = 30])
      : this.name = name,
        this.age = age;

  // 약식 표현. Flutter, Dart에서는 약식 표현을 권장한다.
  // Person(this.name, [this.age = 30]);

  void sayHello() {
    print("Hello my name is $name ,I'm $age years old.");
  }
}
  1. 변수 타입에 ?를 붙인다.
  2. constructor parameter에 [this.인자 = 값]로 감싼다.

🚈 Named Constructor

이름이 있는 생성자이며 여러 생성자를 만들 수 있다는 특징이 있다.
named, optional 파라미터를 사용해서 만들 수 있다.
list나 map등으로 받을때도 사용된다.

void main() {
  var tracer = Player(name: "트레이서", age: 26, team: 'blue', power: 2);
  var tracerBlueBot = Player.createBluePlayer(name: "트레이서_봇", age: 26);
  var tracerRedBot = Player.createRedPlayer("트레이서_봇", 26);

  tracer.sayHello(); // 트레이서. 나이 : 26. blue팀
  tracerBlueBot.sayHello(); // 트레이서_봇. 나이 : 26. blue팀
  tracerRedBot.sayHello(); // 트레이서_봇. 나이 : 26. red팀
}

class Player {
  String name, team;
  int age, power;

  // class를 호출할 때 마다 기본으로 호출되는 기본 constructor
  // named constructor parameter
  Player({
    required this.name,
    required this.age,
    required this.team,
    required this.power,
  });

  // 1. Named constructor
  // Named Parameters 방식
  Player.createBluePlayer({
    required String name,
    required int age,
  })  : this.name = name,
        this.age = age,
        this.team = 'blue',
        this.power = 1;

  // 2. Named constructor
  // Positional Parameters 방식
  Player.createRedPlayer(String name, int age)
      : this.name = name,
        this.age = age,
        this.team = 'red',
        this.power = 1;

  void sayHello() {
    print("${name}. 나이 : ${age}. ${team}팀");
  }
}

List<Map> 으로 감싸진 json 형태를 객체화 시키는 예제

void main() {
  // 3. 객체를 담을 리스트 작성
  List<ToonModel> toonInstances = [];

  // 1. 객체화 하려는 데이터
  List<Map<String, dynamic>> toonList = [
    {'title': '진격의거인', 'thumb': 'img1.jpg', 'id': 1021},
    {'title': '귀멸의칼날', 'thumb': 'img2.jpg', 'id': 2503},
    {'title': '나루토', 'thumb': 'img3.jpg', 'id': 6234},
  ];

  // 4. 객체를 리스트에 넣어준다.
  for (var toon in toonList) {
    final toonInfo = ToonModel.fromJson(toon);
    toonInstances.add(toonInfo);
  }

  // 5. 객체출력
  for (int i = 0; i < toonInstances.length; i++) {
    print(
        "제목 : ${toonInstances[i].title}, 이미지 : ${toonInstances[i].thumb}, 아이디 : ${toonInstances[i].id}");
  }
  /*
  제목 : 진격의거인, 이미지 : img1.jpg, 아이디 : 1021
  제목 : 귀멸의칼날, 이미지 : img2.jpg, 아이디 : 2503
  제목 : 나루토, 이미지 : img3.jpg, 아이디 : 6234
  */
  
}

// 2. 객체화를 위한 틀 만들기
class ToonModel {
  String title, thumb;
  int id;

  ToonModel.fromJson(Map<String, dynamic> json)
      : title = json['title'],
        thumb = json['thumb'],
        id = json['id'];
}

Named Constructor는 Flutter에서 흔하게 사용되는 패턴이다.

🚈 Immutable Programing

Immutable이란 불변성을 뜻하며, Immutable 객체는 객체가 가지고 있는 값을 변경할 수 없는 객체를 의미한다. 즉, 값이 변경될 수 없게 방지한다.

값을 변경하고 싶으면 새로운 객체를 생성하고 변경된 값을 주입해야 한다.

void main() {
  Person person = Person("홍길동", 20);

  person.sayHello();
  
  // immutable이 적용되어 객체의 값 변경불가.
  // person.age = 10;
}

class Person {
	// final 선언
    final String name;
    final int age;

	// const 선언
   const Person(String name, int age)
      : name = name,
        age = age;

  void sayHello() {
    print("Hello my name is $name , I'm $age years old");
  }
}

Immutable 을 사용하려면

  1. constructor 앞에 const를 붙인다.
  2. 해당 Class의 변수 앞에 final을 붙인다.

constfinal은 모두 불변하는 상수를 의미하며 차이가 있다.
const는 compile-time constant로 앱 빌드시 값이 정해진다.
final은 run-time constant로 앱 빌드시에는 값이 정해지지 않지만 앱 실행시 값이 정해진다. (DataTime.now, Device size 등)


🚗 Flutter 사용 예제

모든 위젯을 만들때 StatelessWidget 혹은 StatefulWidget 을 상속받아 위젯을 만들곤 한다. 이 둘은 Widget이라는 객체를 상속받고 있다. Widget은 스스로 변경가능한 상태 값을 갖고 있지 않도록 설계되어 있다.
Flutter의 모든 위젯들은 immutable로 설계되어 있으며, StatefulWidget 마저 immutable 한 클래스이다.(새로운 값을 가질 수 있는 이유는 StatefulWidget 생성시 State<Class>extends 하는 두번째 클래스 때문이다. 두번째 클래스가 mutable 하도록 설계 된듯 하다.)

main.dart

List<String> images = [
  "assets/feed_01.jpeg",
  "assets/feed_02.jpeg",
  "assets/feed_03.jpeg",
];

ListView.builder(
  itemCount: images.length,
  itemBuilder: (context, index) {
    final image = images[index];
    return Feed(
      imageUrl: image,
    );
  },
)

feed.dart

class Feed extends StatefulWidget {
  const Feed({
    Key? key,
    required this.imageUrl,
  }) : super(key: key);

  final String imageUrl;

  
  State<Feed> createState() => _FeedState();
}

class _FeedState extends State<Feed> {

}

예제와 같이 Feed 클래스를 객체화 하기 위해 constructor 앞에 const로 선언하며 변수도 final로 선언한다.


🚗 추가 지식

immuable의 반대는 mutable이다.


reference

Widget과 imutable의 관계

https://velog.io/@dosilv/Flutter-Dart-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-type-operator-function-null-safety#-function

https://papabee.tistory.com/37

profile
개발관련 정리하고 기록하는 블로그 🦦

0개의 댓글