OOP(Object Oriented Programming) - 객체지향 프로그래밍
int, String과 같은 기본 데이터 타입을 사용하여 변수를 선언하면, 해당 변수는 그 타입의 데이터만 저장할 수 있습니다. 클래스를 사용하는 것은 단순히 변수에 저장할 수 있는 데이터의 타입을 확장하는 것 이상의 의미가 있습니다. 클래스를 사용하면, 여러 변수(프로퍼티)와 함수(메서드)를 하나의 유닛으로 그룹화할 수 있습니다. 이렇게 하면, 코드를 더 구조화하고 재사용할 수 있으며, 더 복잡한 데이터 구조와 알고리즘을 더 쉽게 표현할 수 있습니다. 예를 들어, 당신의 Idol 클래스는 두 개의 프로퍼티(name과 members)와 두 개의 메서드(sayHello와 introduce)를 포함하고 있습니다. 이 클래스를 사용하여 Idol 객체를 생성하면, 이 객체는 그룹의 이름과 멤버 리스트를 저장할 수 있으며, 인사말과 멤버 소개를 출력할 수 있는 메서드를 가지게 됩니다. 만약 당신이 int 또는 String과 같은 기본 데이터 타입만 사용하려면, 당신은 이러한 프로퍼티와 메서드를 그룹화하는 방법이 없게 됩니다. 따라서, 클래스를 사용하면 코드를 더 잘 구조화하고 관리할 수 있으며, 더 복잡한 동작을 캡슐화할 수 있습니다.
final 과 const 키워드는 변수가 한 번만 할당 될 수 있음을 나타내지만, 그들 사이에는 몇 가지 차이점이 있습니다.
1. final
- final 변수는 한 번 초기화되면 그 값이 변경될 수 없습니다.
- final 변수는 런타임에 할당 될 수 있습니다. 즉, 런타임 도중에 한 번만 값을 할당할 수 있습니다.
- final 변수의 값은 실행 시간에 계산될 수 있습니다.
2. const
- const 변수는 컴파일 타임에 상수 값으로 초기화 됩니다. 즉, 변수의 값이 소스 코드에서 직접 지정되어 컴파일 시점에 알려져야 합니다.
- const 변수는 변경할 수 없는 상수 값을 참조해야 합니다.
void main() {
// Idol로 타입을 정해준다.
// new Idol 새로운 인스턴스를 생성하겠다.라는 의미이다.
Idol blackPink = const Idol(
'블랙핑크',
['지수', '제니', '리사', '로제'],
);
Idol blackPink2 = const Idol(
'블랙핑크',
['지수', '제니', '리사', '로제'],
);
print(blackPink.name);
print(blackPink.members);
blackPink.sayHello();
blackPink.introduce();
print('----------');
print(blackPink == blackPink2);
// const를 안쓰면 서로 false가 나온다. 새로운 객체가 생성되면 다른 메모리에 저장된다.
// const를 쓰면 같은 인스턴스가 된다.
Idol bts = new Idol(
'BTS',
['RN', '진', '슈가', '제이홉', '지민', '뷔', '정국'],
);
print(bts.name);
print(bts.members);
bts.sayHello();
bts.introduce();
}
// Idol class
// name(이름) - 변수
// members(멤버들) - 변수
// sayHello(인사) - 함수
// introduce(멤버 소개) - 함수
// constructor(생성자)
// Immutable 프로그래밍
class Idol {
final String name; // 거의 대부분에 클래스에는 final을 만들어 버그를 예방해야 한다.
final List<String> members;
// Idol(String name, List<String> members) // constructor(생성자)
// : this.name = name,
// this.members = members;
// Idol(this.name, this.members); // 기본 constructor
const Idol(this.name, this.members); // 기본 constructor
void sayHello() {
print('안녕하세요 ${this.name}입니다.');
}
void introduce() {
print('저희 멤버는 ${this.members}가 있습니다.');
}
}
1. 클래스 선언 :
class Idol {
...
}
여기서 첫 번쩨 'Idol'은 클래스의 이름을 선언하는데 사용됩니다. 이 이름은 클래스의 타입을 참조할 때와 객체를 생성할 때 사용됩니다.
2. 생성자 선언
Idol(String name, List<String> members)
: this.name = name,
this.members = members;
여기서 두 번째 'Idol'은 클래스의 생성자를 선언하는데 사용됩니다. 생성자는 클래스의 객체를 생성할 때 호출되며, 필요한 초기화 작업을 수행합니다. 이 경우, 생성자는 'name'과 'members'라는 두 개의 파라미터를 받아 클래스의 프로퍼티를 초기화합니다.
'String name '은 두 가지 다른 문맥에서 사용되었습니다.
1. 클래스의 프로퍼티 선언 : 객체의 상태를 저장합니다.
2. 생성자의 매개변수 : 객체 생성 시 초기값을 받습니다.
그리고 이 생성자에서, 'this.name = name;' 구문을 사용하여 생성자의 'name' 매개변수로 받은 값을 클래스의 'name' 프로퍼티에 할당합니다.
'this.name'과 'name'은 두 개의 서로 다른 것을 참조합니다.
1. 'this.name' : 여기서 'this.name'은 Idol 클래스의 'name' 프로퍼티를 참조합니다. 'this'키워드는 현재 인스턴스(즉, 생성될 객체)를 참조하므로, 'this.name'는 현재 인스턴스의 'name'프로퍼티를 참조합니다.
2. 'name' : 생성자의 매개변수로 전달된 'name' 값을 참조합니다. 이 'name'은 생성자 함수 내에서만 사용되며, 생성자가 호출될 때 전달된 인수를 저장합니다.
초기화 구문 'this.name = name;' 에서 이 두 참조가 함께 사용됩니다. 이 구문은 생성자에 전달된 'name' 매개변수의 값을 현재 인스턴스의 'name'프로퍼티에 할당하는 역할을 합니다.
void main() {
// Idol로 타입을 정해준다.
// new Idol 새로운 인스턴스를 생성하겠다.라는 의미이다.
_Idol blackPink = _Idol(
'블랙핑크',
['지수', '제니', '리사', '로제'],
);
print(blackPink.firstMember);
blackPink.firstMember = '하하';
print(blackPink.firstMember);
}
// getter / setter
// 데이터를 가져올 떄 / 데이터를 설정할때
// _(언더바) : Private 기능 같은 파일에서만 사용할 수 있다.
class _Idol {
String name;
List<String> members;
_Idol(this.name, this.members); // 기본 constructor
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;
}
}
void main() {
print('------Idol-------');
Idol apink = new Idol(name: '에이핑크', membersCount: 5);
apink.sayName();
apink.sayMemversCount();
print('------BoyGroup------');
BoyGroup bts = new BoyGroup('BTS', 7);
bts.sayName();
bts.sayMemversCount();
bts.sayMale();
print('------GirlGroup------');
GirlGroup blackPink = new GirlGroup(name: '블랙핑크', membersCount: 4);
blackPink.sayName();
blackPink.sayMemversCount();
blackPink.sayFeMale();
print('--------Type Comparison ---------');
print(blackPink is Idol);
print(blackPink is GirlGroup);
print(blackPink is BoyGroup);
print('--------Type Comparison2 ---------');
print(bts is Idol);
print(bts is GirlGroup);
print(bts is BoyGroup);
print('--------Type Comparison2 ---------');
print(apink is Idol);
print(apink is GirlGroup);
print(apink is BoyGroup);
}
// 상속 - inheritance
//
// 상속을 받으면 부모 클래스의 모든 속성을
// 자식 클래스가 부여받는다.
// 프로그램에서 상속은 무조건 부모 클래스에서 자식클래스에게 속성을 넘겨준다. 자식에서 부모는 안된다.
class Idol {
// 이름
String name;
// 멤버 숫자
int membersCount;
Idol({
required this.name,
required this.membersCount,
});
void sayName() {
print('저는 ${this.name}입니다.');
}
void sayMemversCount() {
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({required String name, required int membersCount})
: super(
name: name,
membersCount: membersCount,
);
void sayFeMale() {
print('저는 여자 아이돌입니다.');
}
}
void main(){
TimesTwo tt = new TimesTwo(2);
print(tt.calculate());
TimesFour tf = new TimesFour(2);
print(tf.calculate());
}
// method - functin(class 내부에 있는 함수)
// override - 덮어쓰다 (우선시하다.)
class TimesTwo {
final int number;
TimesTwo(
this.number,
);
//method
int calculate() {
return number * 2;
}
}
class TimesFour extends TimesTwo {
TimesFour(int number,
) : super(number);
@override
// int calculate() {
// return super.number * 4;
// }
int calculate(){
return super.calculate() * 2;
}
}
void main(){
Employee seulgi = Employee('슬기');
Employee chorong = Employee('초롱');
seulgi.name = '코드팩토리';
seulgi.printNameAndBuilding();
Employee.building = '오투타워';
seulgi.printNameAndBuilding();
}
class Employee {
// static은 instance에 귀속되지 않고 class에 귀속된다.
// 알바생이 일하고 있는 건물
static String? building;
// 알바생 이름
String name;
Employee(
this.name,
);
void printNameAndBuilding(){
print('제 이름은 $name입니다. $building 건물에서 근무하고 있습니다.');
}
static void printBuilding(){
print('저는 $building 건물에서 근무중입니다.');
}
}
void main(){
BoyGroup bts = new BoyGroup('BTS');
bts.sayName();
}
// interface
// abstract 우리가 인스턴스를 만들 때 사용하지 말아라
// class IdolInterface{
// String name;
// IdolInterface(this.name);
// void sayName(){}
// }
abstract class IdolInterface{
String name;
IdolInterface(this.name);
void sayName(){}
}
class BoyGroup implements IdolInterface{
String name;
BoyGroup(this.name);
void sayName(){
print('제 이름은 $name입니다.');
}
}
// 상속에 경우는 속성과 기능을 물러주기 위해서
// 인터페이스는 어떤 특수한 구조를 강제하는 것
void main() {
Lecture<String, String> lecture1 = new Lecture('123', 'lecture');
lecture1.printIdType();
Lecture<int, String> lecture2 = new Lecture(123, 'lecture2');
lecture2.printIdType();
}
// generic - 타입을 외부에서 받을때 사용
class Lecture<T, X> {
final T id;
final X name;
Lecture(this.id, this.name);
void printIdType() {
print(id.runtimeType);
}
}
void main(){
Test test = new Test();
}
// Object Oriented Programing
// 객체지향 프로그래밍
// 모든 클래스는 Object를 상속받고 있다.
class Test extends Object{}'Flutter(플러터)' 카테고리의 다른 글
| Dart #4 비동기 프로그래밍(Async Programming) (0) | 2023.09.18 |
|---|---|
| Dart #3 함수형 프로그래밍(Functional Programming) (1) | 2023.09.18 |
| Dart #1 기본기 (0) | 2023.09.17 |