Dart (3) - 객체 지향형 프로그래밍

소밍·2023년 6월 28일
0
post-thumbnail
void main(){
  Idol blackPink = Idol(
    '블랙핑크',
    ['지수','제니','리사','로제']
  );
  
  print(blackPink.name);
  print(blackPink.members);
  blackPink.sayHello();
  blackPink.introduce();
}

class Idol{
  String name;
  List<String> members;
  
  Idol(String name, List<String> members)
    : this.name = name,
      this.members = members;
  
  void sayHello(){
    print('안녕하세요 ${this.name}');
  }
 
  void introduce(){
    print('저희 멤버는 ${this.members}입니다');
  }
}

간결하게 작성하기

void main(){
  Idol blackPink = Idol(
    '블랙핑크',
    ['지수','제니','리사','로제']
  );
  
  print(blackPink.name);
  print(blackPink.members);
  blackPink.sayHello();
  blackPink.introduce();
}

class Idol{
  String name;
  List<String> members;
  
  Idol(this.name, this.members);
  
  void sayHello(){
    print('안녕하세요 ${this.name}');
  }
 
  void introduce(){
    print('저희 멤버는 ${this.members}입니다');
  }
}

named constructor

void main(){
  Idol blackPink = Idol.fromList(
    [
      ['지수','제니','리사','로제'],'블랙핑크'
    ]
  );
  
  print(blackPink.name);
  print(blackPink.members);
  blackPink.sayHello();
  blackPink.introduce();
}

class Idol{
  String name;
  List<String> members;
  
  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}입니다');
  }
}

immutable 프로그래밍

  • 한번 선언한 이후에 변경할 수 없도록 만들기
  • 변수에 final 키워드 추가
  • const로 선언하고 모든 내용을 동일하게 작성하면 같은 인스턴스가 됨. (const를 넣지 않으면 다른 인스턴스로 인식)

getter, setter

  • getter 사용 이유
    데이터를 간단하게 가공할 때 사용, 함수는 로직이 많이 들어갈 때
void main(){
  Idol blackPink = Idol.fromList(
    [
      ['지수','제니','리사','로제'],'블랙핑크'
    ]
  );
  
  Idol aespa = Idol.fromList(
    [
      ['카리나','윈터','닝닝','지젤'],'에스파'
    ]
  );
  
  print(blackPink.firstMember); // 지수
  print(aespa.firstMember); // 카리나
  
  blackPink.firstMember = '솜';
  print(blackPink.firstMember); // 솜
}

class Idol{
	String name;
    List<String> members;
    
    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}입니다');
    }
    
    //getter
    String get firstMember{
    	return this.members[0];
    }
    
    //setter - 값을 새로 지정
    set firstMember(String name){
    	this.members[0] = name;
    }
}

private 변수

  • _ 붙이면 private 속성 부여
  • 외부에서 현재 파일을 불러오더라도 _Idol 클래스를 사용할 수 없음
void main(){
  _Idol blackPink = _Idol.fromList(
    [
      ['지수','제니','리사','로제'],'블랙핑크'
    ]
  );
  
  _Idol aespa = _Idol.fromList(
    [
      ['카리나','윈터','닝닝','지젤'],'에스파'
    ]
  );
  
  print(blackPink.firstMember); // 지수
  print(aespa.firstMember); // 카리나
  
  blackPink.firstMember = '솜';
  print(blackPink.firstMember); // 솜
}

class _Idol{
	String name;
    List<String> members;
    
    _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}입니다');
    }
    
    //getter
    String get firstMember{
    	return this.members[0];
    }
    
    //setter - 값을 새로 지정
    set firstMember(String name){
    	this.members[0] = name;
    }

상속 inheritance

상속을 받으면 부모 클래스의 모든 속성을 자식 클래스가 부여받음

void main(){
  print('------idol------');
  Idol blackPink = Idol(name: '블랙핑크', membersCount: 4);
  blackPink.sayName();
  blackPink.sayMembersCount();
  
  print('------boy------');
  BoyGroup bts = BoyGroup('BTS', 7);
  bts.sayName();
  bts.sayMembersCount();
  bts.sayMale();
  
  print('------girl------');
  GirlGroup ive = GirlGroup('IVE', 6);
  ive.sayName();
  ive.sayMembersCount();
  ive.sayFemale();
  
  print('------type comparison------');
  print(blackPink is Idol); //true
  print(blackPink is BoyGroup); //false
  print(blackPink is GirlGroup); //false
  
  print('------type comparison2------');
  print(bts is Idol); //true
  print(bts is BoyGroup); //true
  print(bts is GirlGroup); //false
  
  print('------type comparison3------');
  print(ive is Idol); //true
  print(ive is BoyGroup); //false
  print(ive is GirlGroup); //true
}


class Idol{
  //이름
  String name;
  int membersCount;
  
  Idol({
    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(
          name: name,
          membersCount: membersCount,
        );
  
  // 보이그룹에만 있는 속성 추가
  void sayMale(){
    print('저는 남자그룹입니다');
  }
}

class GirlGroup extends Idol{
  GirlGroup(
    String name,
    int membersCount,
  ): super(
          name: name,
          membersCount: membersCount,
        );
  
  // 걸그룹에만 있는 속성 추가
  void sayFemale(){
    print('저는 여자그룹입니다');
  }
}

method - class 내부에 있는 함수

override

무언가를 우선시 하겠다, 덮어쓴다는 의미

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

class TimesTwo{
  final int number;
  
  TimesTwo(
    this.number,
  );
  
  //method
  int calculate(){
    return number*2;
  }
}

class TimesFour extends TimesTwo{
  TimesFour(
    int number,
  ) : super(number);
  
   // 메소드 오버라이드
  int calculate(){
    return super.number*4;
    //return super.calculate()*2; 
  }
}

static

static은 인스턴스에 귀속되지 않고 class에 귀속된다.

void main(){
  Employee som = Employee('솜');
  Employee min = Employee('민');
  
  som.name = '슈';
  som.printNameAndBuilding();
  min.printNameAndBuilding();
  
// static은 class에 귀속되기 때문
  Employee.building = '롯데타워';
  som.printNameAndBuilding();
  min.printNameAndBuilding();
  
// static method
  Employee.printBuilding();
}

class Employee{
  // 근무지 static
  static String? building;
  // 근무자 // final로 설정하지 않았다면 추후에 근무자 이름 변경 가능
  String name;
  
  Employee(
    this.name,
  );
  
  void printNameAndBuilding(){
    print('제 이름은 $name 입니다. $building 건물에서 근무하고 있습니다.');
  }
  
// static method
  static void printBuilding(){
    print('저는 $building 건물에서 근무 중입니다.');
  }
}

interface

상속은 속성과 기능을 자식에게 물려주기 위해 사용한다면
인터페이스는 어떤 특수한 구조를 강제하기 위해 사용
abstract 키워드를 붙여 인스턴스를 만들지 못하게 만듦

void main(){
  BoyGroup bts = BoyGroup('BTS');
  GirlGroup ive = GirlGroup('IVE');
  
  bts.sayName(); //제 이름은 BTS 입니다.
  ive.sayName(); //제 이름은 IVE 입니다.
  
  print(bts is IdolInterface); //true 
  print(bts is BoyGroup); //true
  print(bts is GirlGroup); //false
  
  print(ive is IdolInterface); //true
  print(ive is BoyGroup); //false
  print(ive is GirlGroup); //true
}

// interface - 클래스를 만들때 사용! 인터페이스의 형태를 지켜서 클래스를 만듦
abstract class IdolInterface{
  String name;
  
  IdolInterface(
    this.name);
  
  void sayName(); // abstract를 사용하면 함수의 바디 {}를 지워도 됨.
}

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 입니다.');
  }
}

generic

타입을 변수처럼 외부에서 받아서 쓸 수 있도록 함

void main(){
  Lecture<String, String> lecture1 = Lecture('123','lecture1');
  
  lecture1.printIdType(); //String
  
  Lecture<int, String> lecture2 = Lecture(123,'lecture2');
  
  lecture2.printIdType(); //int
}

class Lecture<T, X>{
  final T id; // id 값의 타입이 뭐가 될지 외부에서 인스턴스를 만들 때 선언할 수 있음
  final X name;
  
  Lecture(this.id, this.name);
  
  void printIdType(){
    print(id.runtimeType);
  }
}

oop ; 객체 지향 프로그래밍

모든 class의 최상위 부모는 Object!
class Test{}는 곧 class Test extends Object{} 을 의미

profile
생각이 길면 용기는 사라진다.

0개의 댓글

관련 채용 정보