Dart
Dart 공식문서
다트 ( Dart ) 상속
다트 ( Dart ) 접근 지정자
Dart 의 상속
# 상속
class Person {
String name;
setName(String name) {
this.name = name;
}
showInfo() {
print("name is $name");
}
}
class Student extends Person {
int studentID;
@override
showInfo() {
print("name is $name and id is $studentID");
}
}
- 상속은 객체 지향 프로그래밍의 꽃이라 할 수 있음
- 객체 지향 프로그래밍에서 상속은 클래스의 멤버를 물려주는 것을 의미
- 이때 물려주는 쪽을 부모 클래스 ( 혹은 Super Class ) 라고 하고 상속을 받는 쪽을 자식 클래스 ( 혹은 Sub Class ) 라고 함
- 상속 받는 쪽 ( 자식 클래스 ) 은
extends
키워드를 통해서 상속받고자 하는 부모 클래스를 지정
@override
어노테이션은 부모 클래스의 메서드를 재정의하고 싶을 때 사용
- 재정의한다는 의미는 기존 메서드에서 구현한 내용 대신 다른 동작을 하는 코드를 구현하는 것
# 예시
class Person {
late String name;
setName(String name) {
this.name = name;
}
getName() {
return name;
}
showInfo() {
print("name is $name");
}
}
class Student extends Person {
late int studentID;
@override
showInfo() {
print("name is $name and id is $studentID");
}
}
main() {
Student student = Student();
student.studentID = 2023;
student.setName("Park");
student.showInfo();
}
------------------------------------------------------------------------------------------
# 결과
name is Park and id is 2023
- Student 클래스는 Person 클래스를 상속받고 있음
- 따라서 Student 클래스는 자식 클래스이고 Person 클래스는 부모 클래스
- Person 클래스는 1개의 멤버 변수와 3개의 메서드로 구성되어 있음
- 자식 클래스인 Student 클래스는 이 멤버 변수와 메서드를 모두 상속 받음
- 따라서 해당 멤버 변수와 메서드를 별도로 Student 클래스 내에 선언하지 않아도 사용 가능
- 선언된 위치만 부모 클래스에 있을 뿐이지 자식 클래스 내에 존재하지 않는 것과 같음
- 만약 함수의 기능을 변경하고 싶다면 재정의하면 됨
- 부모 클래스의 showInfo() 메서드를 재정의 하기 위한 방법
- Line 20 을 보면
@override
어노테이션이 있고 이것은 showInfo()
메서드를 재정의하기 위한 것
showInfo()
는 부모 클래스에서는 name 만 출력하고 있음
- 자식 클래스의 멤버 변수인 studentID 도 추가해서 출력하도록 변경
- 이때 자식 클래스의
showInfo()
메서드 내부를 주목
- Line 22 를 보면 부모 클래스의 메서드인 getName() 메서드에 접근하기 위해서 super 라는 키워드를 사용
- super 는 부모 클래스를 가리키지만 생략도 가능
- 자식 클래스는 이미 부모 클래스의 getName() 메서드도 상속 받았기 때문
- 또한 getName() 을 통해서 name 에 접근하지 않고 곧바로 name 변수를 출력해도 됨
- 마지막으로 설펴볼 것은 Line 5 의 this 키워드
- this 는 해당 인스턴스를 가리킴
- 여기서는 this.name 이 Person 클래스의 인스턴스 변수인 name 을 가리키고 name 은 setName(String name) 메서드의 인자를 가리킴
- 변수명이 동일하기 때문에 구분하기 위해서 this 로 인스턴스 변수를 명확히 가리킨 것
- 상속은 왜 사용할까?
- 일단 코드를 재사용하기 때문에 클래스가 간소화되고 수정 및 추가가 쉬워짐
- 위 코드를 기준으로 보면 Student 클래스는 부모 클래스에 있는 멤버들을 일일이 다시 선언할 필요가 없었음
- 따라서 Student 클래스는 매우 간결해짐
- 그리고 해당 클래스에서 필요한 기능을 쉽게 추가 가능
- studentID 변수를 추가했고 showInfo() 메서드도 필요에 맞게 수정함
- 만약 Student 클래스 하나가 아닌 Employee 클래스 ∙ Manager 클래스 ∙ Programmer 클래스 등 사람과 관련된 수많은 객체를 위한 클래스를 생성한다고 생각해보면 더욱 코드 재사용성이 값진 의미를 가짐
- 또한 Employee 클래스 하위에 Manager 클래스 ∙ Programmer 클래스를 두는 방식을 또 한번 코드를 재사용할 수 있고 각 객체의 특징에 대해 유연하게 정의하고 수정 및 추가가 가능
Dart 의 접근 지정자
캡슐화
- 간단하게 캡슐화를 설명하면 어떤 객체가 어떤 목적을 수행하기 위한 데이터 ( 멤버 변수 ) 와 기능 ( 메서드 ) 을 적절하게 모으는 것
추상화
- 추상화는 어떤 객체의 공통된 데이터와 메서드를 묶어서 이름 ( 클래스명 ) 을 부여하는 것
- 단순히 말하면 클래스를 만드는 일
- 공통 속성을 추출해나가는 과정을 추상화라고 함
- 추상화를 잘한다면 중복되는 부분을 많이 없앨 수 있어 코드 재사용률을 높일 수 있음
접근 지정자
- 접근 지정자는 클래스의 멤버 변수 또는 메서드 앞에 선언되고 종류에 따라 해당 멤버들에게 접근할 수 있는 범위가 달라짐
- Java 의 경우 네 가지 접근 지정자가 존재
- 그 중에 private 라는 접근 지정자는 동일 클래스 내에서만 접근이 가능
- 그리고 public 은 접근 범위에 제한 없이 모든 곳에서 접근 가능
# 접근 지정자
class Person {
String name;
int _age;
eat() {
print("eat");
}
_sleep() {
print("sleep");
}
}
- 다트의 접근 지정자는 딱 두 종류로 private 과 publi
- 하지만 접근 범위가 자바와 다름
- 다트에서 private 멤버의 접근 범위 는 동일 클래스가 아니라 라이브러리 (=자바 기준으로 패키지)
- 또한 접근 지정자의 키워드도 다름
- 다트는 기본적으로 아무런 키워드가 없을 경우 public
- private 으로 선언하기 위해서는 변수나 메서드 앞에
_
( 밑줄 ) 을 붙여야 함
- 위의 코드에서
_
가 붙은 _age 와 _sleep() 은 private 이고 name 과 eat() 은 public
# 예시 1
import 'package:dartEx01/src/Person.dart';
main() {
Person p = Person();
p.eat();
}
# 예시 2
class Person {
String name;
int _age;
eat() {
print("eat");
}
_sleep() {
print("sleep");
}
}
- Person 클래스를 main.dart 가 아닌 외부의 Person.dart 에 선언
- main.dart 에서 Person.dart 를 import 하고 public 메서드인 eat() 을 호출
- 이때 정상적으로 호출이 되어 eat 이 출력됨
- 하지만 주석 처리된 _sleep() 을 호출하면 에러가 발생
- private 인 _sleep() 은 main.dart 에서 접근이 불가능하기 때문