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 |