🐦 Flutter

dart OOP

ji-hyun 2022. 5. 30. 15:56

class 안에 final 을 써줘야 바깥에서 수정하는 것을 막을 수 있다.

 

void main(){
  Idol bts = Idol("방탄소년단", ["지수", "제이홉"]);
  bts.name = "에이핑크";    // block
}

class Idol {
  final String name;
  final List<String> members;
  
  Idol(this.name, this.members);
}

 

 

 

 

 

void main(){
  Idol bts = const Idol("방탄소년단", ["지수", "제이홉"]);

}

class Idol {
  final String name;
  final List<String> members;
  
  const Idol(this.name, this.members);
}

 

const 의 기능은 원래 한번 선언하면 못 바꾸는 기능이 있었다.

그리고 빌드 당시 타입을 알 수 있어야 했다.

 

 

 

void main(){
  Idol bts = const Idol(DateTime.now().toString(), ["지수", "제이홉"]);
// 위는 에러.. const == 빌드 당시 타입을 알아야 함
}

class Idol {
  final String name;
  final List<String> members;
  
  const Idol(this.name, this.members);
}

 

 

 

 

 

 

void main(){
  Idol bts = const Idol('방탄소년단', ["지수", "제이홉"]);

}

class Idol {
  final String name;
  final List<String> members;
  
  Idol(this.name, this.members);   // const 인스턴스 만들려면 무조건 const constrctor 로 만들어줘야 함
}

 

Cannot invoke a non-'const' constructor where a const expression is expected. Idol bts = const Idol('방탄소년단', ["지수", "제이홉"]);

 

 

 

 

void main() {
  Idol blackPink = const Idol('블랙핑크', ['지수', '제니', '리사', '로제']);  //
 Idol blackPink2 = const Idol('블랙핑크', ['지수', '제니', '리사', '로제']);  //
  
  print(blackPink.name);
  print(blackPink.members);
  blackPink.sayHello();
  blackPink.introduce();
  
  Idol bts = Idol.fromList([['RN', '제이홉', '슈가', '진'], '방탄소년단']);
  
  print(bts.name);
  bts.sayHello();
  
  
  print('-------------');
  print(blackPink == blackPink2);
}

class Idol {
  final String name;
  final List<String> members;

  const Idol(this.name, this.members);   

  Idol.fromList(List values)
      : this.members = values[0],
        this.name = values[1];

  void sayHello() {
    print("안녕하세요 ${this.name}입니다");
  }

  void introduce() {
    print("저희 멤버는 ${this.members}가 있습니다");
  }
}

 

 

위의 2줄에 const 를 붙이지 않으면 blackPink == blackPink2 의 결과가 false 이고,

붙이면 blackPink == blackPink2 의 결과가 true 이다.

 

 

 

 

 

 

 

class Idol {
  String name;
  List<String> members;

  const Idol(this.name, this.members);

  Idol.fromList(List values)
      : this.members = values[0],
        this.name = values[1];

  void sayHello() {
    print("안녕하세요 ${this.name}입니다");
  }

  void introduce() {
    print("저희 멤버는 ${this.members}가 있습니다");
  }
}

 

위는 에러가 나는데 에러 내용은

Constructor is marked 'const' so all fields must be final. const Idol(this.name, this.members);

 

 

final String name;
final List<String> members;

이렇게 final 을 붙여야 함

 

 

 

 

getter / setter

데이터를 가져올 때 / 데이터를 설정할 때

 

 

void main() {
  Idol blackPink = Idol('블랙핑크', ['지수', '제니', '리사', '로제']);
  
 

  Idol bts = Idol.fromList([
    ['RN', '제이홉', '슈가', '진'],
    '방탄소년단'
  ]);
 
  
  blackPink.firstMember = "코드팩토리";   // set
  print(blackPink.members);

}

class Idol {
  final String name;
  final List<String> members;

  const Idol(this.name, this.members);
  

  Idol.fromList(List values)
      : this.members = values[0],
        this.name = values[1];

  void sayHello() {
    print("안녕하세요 ${this.name}입니다");
  }

  void introduce() {
    print("저희 멤버는 ${this.members}가 있습니다");
  }
  
  
  String get firstMember {
    return this.members[0];
  }
  
  set firstMember(String name){
    this.members[0] = name;
  }
}

 

set 의 parameter 에는 하나의 인자만 들어올 수 있다.

 

 

 

 

 

 

 

 String getFirstMember() {
    return this.members[0];
  }
  
  String get firstMember {
    return this.members[0];
  }

 

이 둘의 차이는 

기능의 차이는 없지만 늬앙스의 차이

 

get 은 데이터를 간단히 가공할 때(첫번째 데이터...)

함수는 로직이 많을 때

 

 

 

 

 

 

private 변수

_ 기호

같은 파일 내에서만 사용이 가능하다.

설사 다른 파일에서 import 해서 사용한다고 하더라도 private 변수는 사용이 불가능하다.

 

 

void main() {
  _Idol blackPink = _Idol('블랙핑크', ['지수', '제니', '리사', '로제']);
  
 

  _Idol bts = _Idol.fromList([
    ['RN', '제이홉', '슈가', '진'],
    '방탄소년단'
  ]);
 
  
  blackPink.firstMember = "코드팩토리";
  print(blackPink.members);

}

class _Idol {
  final String name;
  final List<String> members;

  const _Idol(this.name, this.members);
  

  _Idol.fromList(List values)
      : this.members = values[0],
        this.name = values[1];

  void sayHello() {
    print("안녕하세요 ${this.name}입니다");
  }

  void introduce() {
    print("저희 멤버는 ${this.members}가 있습니다");
  }
  
  String getFirstMember() {
    return this.members[0];
  }
  
  String get firstMember {
    return this.members[0];
  }
  
  set firstMember(String name){
    this.members[0] = name;
  }
}

 

 

 

 

 

 

 

class Idol {
  String name;
  int membersCount;

  Idol({                          // contructor 생성
    required this.name,
    required this.membersCount,
  });

  void sayName() {
    print('저는 ${this.name}');
  }

  void sayMembersCount() {
    print("${this.name} 은 ${this.membersCount} 명의 멤버가 있습니다.");
  }
}

class BoyGroup extends Idol {
  BoyGroup(
    String name,
    int membersCount,
  ) : super(                         // 부모 constructor 생성
          name: name,
          membersCount: membersCount,
        );
}

 

 

 

 

class GirlGroup extends Idol {
  GirlGroup(     // 자식 contructor 생성
    String name,
    int membersCount,
  ): super(name: name, membersCount: membersCount);   // 부모 constructor 생성
}

 

 

 

 

 

 

void main() {
  TimesTwo tt = TimesTwo(2);
  
  print(tt.calculate());
}

// method - function (class 내부에 있는 함수)
// override - 덮어쓰다 (우선시하다)

class TimesTwo {
  final int number;

  TimesTwo(this.number); // positional parameter
  
  // method
  int calculate(){
    return number * 2;  
  }
}

 

4 를 반환

 

 

 

 

 

 

 

override

 

void main() {
  TimesTwo tt = TimesTwo(2);

  print(tt.calculate());
  
  TimesFour tf = TimesFour(2);
  
  print(tf.calculate());
}

// method - function (class 내부에 있는 함수)
// override - 덮어쓰다 (우선시하다)

class TimesTwo {
  final int number;

  TimesTwo(this.number); // positional parameter

  // method
  int calculate() {
    return number * 2;
  }
}

class TimesFour extends TimesTwo {
  TimesFour(
    int number,
  ) : super(number);

  @override
  int calculate() {
    return super.calculate() * 2;
  }
}

 

 

 

 

 

 

 

 

 

void main() {
  Employee seulgi = Employee("슬기");
  Employee chorong = Employee("초롱");
  
  seulgi.name = "코드팩토리";
  seulgi.printNameAndBuilding();
  chorong.printNameAndBuilding();
}


class Employee {
  // static 은 instance 에 귀속되지 않고 class 에 귀속된다.
  // 알바생이 일하고 있는 건물
  
  static String? building;
  // 알바생 이름
  String name;
  
  Employee(
  this.name,);
  
  void printNameAndBuilding(){
    print("제 이름은 $name 입니다. $building 건물에서 근무하고 있습니다.");
  }
  
  static void printBuilding(){
    print("저는 $building 건물에서 근무중입니다.");
  }
}

 

제 이름은 코드팩토리 입니다. null 건물에서 근무하고 있습니다.
제 이름은 초롱 입니다. null 건물에서 근무하고 있습니다.

 

이게 인스턴스에 귀속된다는 의미이다.

 

 

 

 

 

class 에 귀속된다는 의미는??

 

void main() {
  Employee seulgi = Employee("슬기");
  Employee chorong = Employee("초롱");
  
  seulgi.name = "코드팩토리";
  seulgi.printNameAndBuilding();
  chorong.printNameAndBuilding();
  
  Employee.building = "오투타워";
  
  seulgi.printNameAndBuilding();
  chorong.printNameAndBuilding();
}


class Employee {
  // static 은 instance 에 귀속되지 않고 class 에 귀속된다.
  // 알바생이 일하고 있는 건물
  
  static String? building;
  // 알바생 이름
  String name;
  
  Employee(
  this.name,);
  
  void printNameAndBuilding(){
    print("제 이름은 $name 입니다. $building 건물에서 근무하고 있습니다.");
  }
  
  static void printBuilding(){
    print("저는 $building 건물에서 근무중입니다.");
  }
}

 

 

제 이름은 코드팩토리 입니다. null 건물에서 근무하고 있습니다.
제 이름은 초롱 입니다. null 건물에서 근무하고 있습니다.
제 이름은 코드팩토리 입니다. 오투타워 건물에서 근무하고 있습니다.
제 이름은 초롱 입니다. 오투타워 건물에서 근무하고 있습니다.

 

모두 오투타워로 바뀌는 것을 볼 수 있다.

static 때문

 

 

 

 

 

interface

 

void main(){
  
}


// interface
class IdolInterface {
  String name;

  
  IdolInterface(this.name);
  
  void sayName() {}
}
  
  
// implements -> interface 쓸 떄 사용
class BoyGroup implements IdolInterface {
  String name;
  
  BoyGroup(this.name);
  
  void sayName(){}
}

 

interface 를 쓸 때는 똑같이 맞춰줘야 한다. 안그러면 에러 발생.

Error: The non-abstract class 'BoyGroup' is missing implementations for these members: - IdolInterface.sayName

 

interface 는 강제하는 역할이라고 보면 된다.

 

 

 

 

 

void main(){
  BoyGroup bts = BoyGroup('BTS');
  GirlGroup apink = GirlGroup("APINK");
  
  
  bts.sayName();
}


// interface
class IdolInterface {
  String name;

  
  IdolInterface(this.name);
  
  void sayName() {}
}
  
  
// implements -> interface 쓸 떄 사용
class BoyGroup implements IdolInterface {
  String name;
  
  BoyGroup(this.name);
  
  void sayName(){
    print("제 이름은 $name 입니다.");
  }
}


class GirlGroup implements IdolInterface {
  String name;
  
  GirlGroup(this.name);
  
  void sayName(){
    print("제 이름은 $name 입니다.");
  }
}

 

interface 는 어떤 특수 구조를 강조하기 위해서 사용한다고 생각하면 된다.

반면 상속은 어떤 특성을 물려주기

 

 

 

 

 

void main(){
  IdolInterface test = IdolInterface("블랙핑크");  // 이렇게 실수로 인터페이스를 사용해버릴 수 있다.
}



// interface
class IdolInterface {
  String name;

  
  IdolInterface(this.name);
  
  void sayName() {}
}

 

 

인터페이스는 인스턴스화 시키지 않는다.

하지만 위의 코드와 같이 실수로 누가 인터페이스를 인스턴스화 시켜버릴 수도 있다.

그럴 때 막는 방법은 다음과 같다.

 

 

 

 

// interface
abstract class IdolInterface {
  String name;

  
  IdolInterface(this.name);
  
  void sayName() {}
}

 

abstract 키워드를 써주면 된다.

= 인스턴스화 시키지 말라는 뜻

 

 

 

class Test extends Object {
  
}

 

원래 class 는 이 문법이 생략되어 있는 것이다. 

그래서 객체지향 프로그래밍이라고 부르는 것

 

'🐦 Flutter' 카테고리의 다른 글

Flutter 생명주기  (0) 2022.07.05
[Flutter] json 파싱 정보글 모음  (0) 2022.06.24
dart 비동기 프로그래밍  (0) 2022.06.02
dart 함수형 프로그래밍  (0) 2022.05.31
flutter 기본 문법  (0) 2022.05.28