OOP (객체 지향 프로그래밍)
class변수, 함수
Instance를 만들 수 있음.
void main(){
Idol blackPink = Idol('블랙핑크', ['1','2','3','4','5']);
Idol blackPink2 = Idol('블랙핑크', ['1','2','3','4','5']);
// blackpink, 2 랑은 다름.
//그런데 const로 만들면 두개가 같아짐.
//같은 인스턴스로 만들어짐.
print(blackPink.name);
print(blackPink.members);
blackPink.sayHello();
blackPink.introduce();
Idol bts = Idol(
'BTS',
['RM', '진', '...'];
)
Idol bts = Idol.fromList([
['RM', '진', '...'],
'BTS',
]);
}
/**
* Idol class
name (이름) - 변수
members(멤버들) - 변수
sayHello (인사) - 함수
introduce (멤버소개) - 함수
constructor(생성자)
*/
class Idol {
String name = '블랙핑크';
List<String> members = ['지수', '제니', '리사', '로제'];
//Idol(String name, List<String> members)
//: this.name = name,
// this.members = members;
// 위와 동일하다.
//Idol(this.name, this.members);
// 이런식으로도 constructor를 구현할 수 있다.
Idol.fromList(List values)
: this.members = values[0],
this.name = values[1];
void SayHello(){
print('안녕하세요 ${this.name} 입니다.');
}
void introduce(){
print('저희는 ${this.members} 있습니다.');
}
뭐 이렇게 쓸수 있다. 값을 바꾸지 못하게 하기 위해
final String name;
final List<String> members;
이렇게 대부분의 class 안에는 final로 선언해준다.
constructor 앞에는 const를 입혀준다.
class getter, setter
// getter/ setter
// 데이터 가져올 때, 데이터 설정할 때,
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]
}
set firstMember(String name){
this.members[0] = name;
}
}
void main() {
Idol blackPink = Idol ('블랙핑크' , ['','','','','',]);
Idol bts = Idol ('BTS' , ['','','','','',]);
print(blackPink.firstMember);
print(bts.firstMember);
// 이렇게 하면 setter 를 부름
blackPink.firstMember = '우하하';
// setter 의 변수 Stirng name에 우하하를 가져옴.
}
- 왜 getter 를 사용하냐 그냥 함수 만들어서 하면 되지. 사실상 기능적인 차이는 없다. getter는 간단하게 가공할 때 사용한다고 보면 됨. 함수는 로직이 많이 들어가는 때에 사용한다.
뭐 근데 막 써도 됨.
- final 지정하면 setter를 못쓰는거 아니냐 그래서 사실상 현대 프로그래밍에서 굉장히 안쓰는 기술임.
Private 변수
파일 밖에서 외부에서 사용하는 변수
변수 앞에 _ 를 붙여주면 됨.
상속
상속 - inheritance
상속을 받으면 부모 클래스의 모든 속성을 자식 클래스가 부여받는다.
class Idol {
//이름
String name;
int memberCount;
Idol({
required this.name;
required this.memberCount;
})
void sayName() {
print('저는 ${this.name} 입니다.');
}
void sayMemberCount() {
print('${this.name}는 ${this.memebercount} 명 입니다.');
}
}
class BoyGroup extends Idol{
BoyGroup(String name, int memebercount)
: super(
name: name,
memberCount: memberCount
);
void sayMail(){
print('저는 남자 아이돌입니다.');
}
}
class GirlGroup extends Idol {
GirlGroup(
String name,
int memberCount,
) : super(
name: name,
memberCount : memberCount,
);
void sayFemale(){
print('저는 여자아이돌입니다.');
}
}
void main(){
Idol apink = Idol(name : '에이핑크', memberCount : 5);
apink.sayName();
apink.sayMemberCount();
// 이렇게 상속받아서 사용할 수 있다,
BoyGroup bts = BoyGroup('BTS', 7);
bts.sayMemberCount();
bts.sayName();
bts.sayMail();
// apink.sayMail()은 사용할 수 없음 (위로 올라갈 수 없음)
GirlGroup redvelbet = GirlGroup('Red Velvet', 5);
redvelbet.sayMemberCount();
redvelbet.sayName();
redvelbet.sayFemale(); // apink, bts에서는 sayFemale()을 사용할 수없음
// 타입은 부모의 타입을 가져간다.
print(apink is Idol); // true
print(apink is BoyGroup); // false
print(apink is GirlGroup); // false
print(bts is Idol); // true
print(bts is BoyGroup); // true
print(bts is GirlGroup); // false
print(redvelbet is Idol); // true
print(redvelbet is BoyGroup); // false
print(redvelbet is GirlGroup); // true
}
주의 할 점은 super 안에서 변수 넣어줘야하는 부분
또 자식 - 부모로 갈 수 없음 자식 - 자식으로도 갈 수 없음
메소드 오버라이딩
메소드 : 클래스 안에 있는 함수 override - 덮어쓰다.
class TimesTwo {
final int number;
TimesTwo(this.number,);
//method
int calculate(){
return number * 2;
}
}
class TimesFour extends TimesTwo {
final int number;
TimesFour(int number) : super(number);
//method
@override
int calculate(){
return super.calculate() * 2;
}
}
void main(){
TimesTwo tt = TimesTwo(2);
print(tt.calculate()); // 4
TimesFour tf = TimesFour(2);
print(tf.calculate());
}
이런식으로 overriding 할 수 있다.
Static
class Employee{
// static은 insatance에 귀속되지 않고 class에 귀속된다.
// 알바생이 일하고 있는 건물
static String? building;
// 알바생 이름
final String name;
Employee(this.name);
void printNameAndBuilding(){
print('제 이름은 $name 입니다. $building 건물에서 근무하고 있습니다.');
}
static void printBuilding(){
print('저는 $building 건물에서 근무중입니다.');
}
}
void main(){
Employee seulgi = Employee('슬기');
Employee chorong = Employee('초롱');
seulgi.name = '코드팩토리';
seulgi.printNameAndBuilding(); // 이름은 다르게 나옴
chorong.printNameAndBuilding(); // 이름은 다르게 나옴
// 건물명은 null로 동일하게 나옴.
Employee.building = '오투타워';
// 클래스 값으로 넣을 수 있따.
seulgi.printNameAndBuilding(); // 빌딩 값은 똑같이 나옴
chorong.printNameAndBuilding(); //빌딩 값은 똑같이 나옴
Employee.printBuilding(); // 그냥 클래스로 호출할 수 있음.
}
자 이런식으로 static 키워드를 사용할 수 있다.
Interface
void main(){
}
// Interface
abstract class IdolInterface{ // 추상적으로 만들면 이걸로 인스턴스 만들지 못하게 막을 수 있음.
String name;
IdolInterface(this.name);
void sayName() // 함수의 바디 없어도 됨.
}
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 입니다.');
}
}
void main(){
BoyGroup bts = BoyGroup('BTS');
GirlGroup apink = GirlGroup('apink');
bts.sayName();
apink.sayName();
print(bts is IdolInterface); // true
print(bts is BoyGroup); // true
}
interface라는 애는 class의 형태를 만들어두는 거라고 보면 됨.
## generic
class Lecture<T>{
final T id; // id 값의 type을 동적으로 지정할 수 있음
final String name;
Lecture(this.id, this.name);
void printIdType(){
print(id.runtimeType);
}
}
void main(){
Lecture<String> lecture1 = Lecture('123', 'lecture1');
lecture1.printIdType(); // String
Lecture<int> lecture1 = Lecture(123, 'lecture2');
lecture2.printIdType(); // Int
}
타입을 외부에서 받을 때
## oop에 대하여…
void main(){
Test test = Test();
}
class Test
이렇게만 해도 Test는 Object를 상속을 하고 있다. 그러므로 Object안의 메서드들을 사용할 수 있다. 그래서 우리는 oop라고 부른다.
이게 끝