[Dart] 5. 상속, 접근 지정자, Getter Setter
5. 상속, 접근 지정자, Getter Setter
class Person {
String? name;
setName(String name) {
this.name = name;
}
getName() {
return name;
}
showInfo() {
print('name is $name');
}
}
class Student **extends** Person {
int? studentID;
**@override**
showInfo() {
print('name is **${super.getName()}** and id is $studentID');
}
}
main() {
Student student = Student();
student.studentID = 2020;
student.setName("Kim");
student.showInfo();
}
Student 클래스는 Person 클래스를 상속받음
Student : 자식 클래스
name, setName(), getName(), showInfo() 모두 상속 받음, 재 선언 하지 않아도 됨
Person : 부모 클래스
함수의 기능을 재정의
@override 어노테이션을 붙이고 재정의하면 된다.
부모 클래스의 메소드인 getName()에 접근하기 위해서 super 라는 키워드 사용 - 생략해도 무관
객체지향 특징
- 추상화 : 공통된 데이터와 메서드를 묶어 이름을 부여 ex) Person class
- 캡슐화 : 어떤 객체가 어떤 목적을 수행하기 위한 데이터( 멤버변수)와 기능(메서드)을 적절하게 모으는 것
→ 하나의 기능을 수행하는 객체를 만드는 것
- 상속
- 다형성
접근 지정자
클래스의 멤버 변수 또는 메서드 앞에 선언되고 종류에 따라 해당 멤버들에게 접근할 수 있는 범위가 달라진다.
public
아무런 키워드 없을 때 public
private
접근 범위 : 라이브러리 ( java의 package )
변수나 메서드 앞에 _ 붙여야 함
int _age;
_sleep() {
}
Getter Setter
멤버 변수를 private으로 선언하고 해당 변수에 접근할 수 있는 메소드는 public으로 선언하면 멤버 변수에 직접적으로 접근하는 것을 막을 수 있다.
class Person {
String _name =''; // private
String get name => _name;
set name(String name) => _name = name;
}
main() {
Person person = Person();
person.name = 'Kim';
print(person.name);
}
추상클래스
추상메소드를 가질 수 있는 클래스
추상 메소드 ( abstract method )
메소드 선언은 되어 있지만 바디가 정의되지 않은 형태
// 추상클래스
abstract class Person {
eat();
}
class Developer implements Person {
@override
eat() {
print('Developer eat a meal');
}
}
main() {
Person person = Developer();
person.eat();
}
추상 클래스 Person의 추상 메서드인 eat()을 오버라이딩 해야한다.
추상 클래스에서 반드시 추상 클래스만 존재하는 것은 아니다.
But, 일반 메서드도 반드시 임플리먼트 하는 클래스에서 반드시! 재정의 되어야 한다. @override 는 생략 가능
여러 개를 임플리먼트 할 수 있다.
List : 배열 , 순서가 있고 중복 허용
Set : 순서가 없고 중복 허용 X
Map : key-value로 구성, 키는 중복되지 않고 값은 중복 가능
List
List<dynamic> list1 = ['yy','jj','zz',2323,444];
for (int i = 0; i<list1.length;i++){
print(list1[i]);
}
List 여러 타입의 데이터를 섞어서 넣고 싶으면
List<dynamic>
List<var>
사용하면 됨
Set
Set<dynamic> testSet = {1,2.5,'test'};
testSet.add(1);
testSet.add(1);
testSet.add(1);
testSet.add(1);
testSet.add(3);
testSet.add(4);
testSet.add(3);
testSet.add('test');
testSet.add('korea');
for(dynamic each in testSet) {
print(each);
}
- 순서가 없기 때문에 각 요소에 인덱스로는 접근 불가
- for .. in 문을 통해 접근 가능
- 중복허용 안하기 때문에 같은 값을 여러 번 추가해도 단 하나만 존재한다.
- { }로 초기값 세팅
Map
key - value 로 이루어짐
Map<int, String> testMap = {
1:'Red',
2:'Orange',
3:'Yellow',
};
testMap[4] = 'Green';
print(testMap);
print(testMap[1]);
print(testMap[5]);
결과
{1: Red, 2: Orange, 3: Yellow, 4: Green} Red null
제네릭 타입
변수 타입을 명확히 표현할 수 있다, 반복되는 코드를 줄일 수 있다.
어떤 자료구조를 만들 때, String 도 지원하고 싶고 Integer도 지원하고 싶고, 많은 타입을 지원하길 원할 때
각 타입에 대해 만들지 않고 다 지원할 수 있는 타입 생성
타입 | 설명 |
<T> | Type |
<E> | Element |
<K> | Key |
<V> | Value |
<N> | Number |
<> : 타입 매개변수 지정
<> 에 타입 매개변수를 선언하는 것을 매개변수화 타입을 정의한다고 한다.
타입 매개변수
- 클래스 생성 시 생성자에서 사용
- 함수 호출 시 인자 값을 전달하기 위해 사용
// 제네릭타입
class Person {
eat() {
print('Person eats a food');
}
}
class Student extends Person {
eat() {
print('Student eats a hambuger ');
}
}
class Manager<T extends Person> {
eat() {
print("Manager eats a sandwich");
}
}
class Dog {
eat() {
print('Dog eats a dog food');
}
}
main() {
var manager1 = Manager<Person>();
manager1.eat();
var manager2 = Manager<Student>();
manager2.eat();
var manager3 = Manager();
manager3.eat();
var manager4 = Manager<Dog>(); // error
}
제네릭 메서드
class Person {
T getName<T>(T param) {
return param;
}
}
main() {
var person = Person();
print(person.getName<String>('Kim'));
// var manager1 = Manager<Person>();
}
<String>
출처 : https://brunch.co.kr/brunchbook/dartforflutter 스터디하며 정리한 글입니다. 감사합니다.