지난 포스팅에 이어 클래스에 대한 내용 두 번째 포스팅 스타뚜
다트의 추상화 클래스에 대해 알아보자.
추상화 클래스를 상속받는 클래스들은 추상화 클래스가 가지고 있는 메서드를 필수로 갖게 한다.
예시를 들어보자.
abstract class Human{
void walk();
}
walk
라는 메서드를 가진 Human
추상화 클래스를 만들었다.
위에 내용에 따라서 이 클래스를 상속받는 모든 클래스들은 walk
라는 메서드를 필수로 가져야 한다.
단, 여기서 추상화 클래스의 장점은 이 walk
메서드의 내용을 자유롭게 구현할 수 있다는 것이다!
abstract class Human{
void walk();
}
class Boy extends Human{
void walk(){
print("Boy is walking");
}
}
walk
메서드는 필수로 가지고 있어야 하나 그 내용은 자유롭게 구현할 수 있다.
위에서 잠시 언급했던 상속에 대해 다뤄보자.
(항상 클래스를 배울 때는 상속에 대한 내용이 제일 어려운거 같다,,)
Human
클래스와 이 클래스를 상속받는 Player
클래스를 만들어 볼 것이다.
class Human{
final String name;
Human(this.name); // constructor
void sayHello(){
print("Hi, My name is $name!");
}
}
enum Team {red, blue}
class Player extends Human{
final Team team;
// constructor
// name을 Human(부모 클래스)로 전달해주기 위해 : super() 사용
Player({required this.team, required String name}) : super(name);
}
void main(){
var player = Player(team: Team.red, name: 'sso');
}
위의 코드에서 주의깊게 봐야하는 코드는 super
이다!
현재 Player
라는 클래스는 Human
클래스를 상속받는다.
따라서 Human
클래스가 부모 클래스인 것이다.
이를 상속받는 Player
클래스는 Human
클래스에 선언된 내용들을 모두 가져와서 사용할 수 있다. 하지만 name
을 사용하기 위해서는 부모 클래스인 Human
에 있는 생성자로 name
을 전달해줘야 한다.
이때 사용하는게 바로 super
이다.
사용 방법
- 자식 클래스의 생성자 뒤에
:
을 찍고super(부모클래스로 보낼 변수)
이렇게 해주면 된다.
즉, **super
는 부모 클래스에 접근하고 상호작용을 할 수 있게 해주는 역할을 한다.
그렇다면 좀 더 깊이 들어가서 부모 클래스에 있는 메서드를 커스터마이징 하고 싶다면 어떻게 해야 하는 지 알아보자.
class Human{
final String name;
Human(this.name); // constructor
void sayHello(){
print("Hi, My name is $name!");
}
}
enum Team {red, blue}
class Player extends Human{
final Team team;
Player({required this.team, required String name}) : super(name);
void sayHello(){
// 부모 클래스 내용 그대로 가져옴
**super.sayHello(); //** print("Hi, My name is $name!");
// 여기서부터는 커스터마이징 내용들
print("I play for ${team}!")
}
}
void main(){
var player = Player(team: Team.red, name: 'sso');
}
우선 @override
키워드를 선언해 부모 클래스의 sayHello
메서드를 직접 만드는 메서드로 대체한다는 의미이다.
그렇게 함수를 가져왔으면 이제 원하는 대로 커스터마이징 하면 된다.
그 중에서 super.sayHello();
를 잘 살펴보면 Human.sayHello
가 아닌 super
키워드를 사용한 것을 볼 수있다. 자식 클래스에서 부모 클래스를 호출할 때는 직접 쓰는 것이 아닌 super
가 부모 클래스의 이름 역할을 한다고 생각하면 이해하기 수월할 것 같다.
우리가 지금까지 만든 클래스들은 항상 생성자를 가지고 있었다.
물론 생성자가 없이도 클래스를 만들 수 있는데 이러한 클래스들을 mixin
이라고 부른다!
// mixin 클래스 Strong, Quick
class Strong{
final double level = 1500.99;
}
class Quick{
void runQuick(){
print("ruuuun!");
}
}
class Player with Strong, Quick{...}
위의 예시처럼 mixin
클래스들은 그냥 메서드나 속성들만 가지고 있을 뿐 생성자를 가지고 있지 않다.
이런 mixin
클래스들 활용할 수 있게 해주는 키워드가 바로 with
이다.
위의 예시에서 Player
클래스는 Strong
, Quick
클래스를 with
를 사용해 가져왔으므로 Player 클래스를 사용해 생성자를 만들었다면 player.runQuick()
이런 식으로 mixin
클래스에 있는 속성들을 가져와서 사용할 수 있다!
따라서 with
의 역할은 단순히 속성들을 끌어와서 사용하기 위한 용도인 것이다. 이런 mixin
클래스들은 재사용이 많이 되는 속성이나 함수를 가지고 있는 클래스를 선언할 때 쓰이기 좋다!
여기까지 플러터에 대해 배워보기 전 다트의 아주 기본적인 문법을 알아보았다.
사실 여기까지의 내용은 정말 다트의 일부분이기 때문에.... 개발 공부를 하면서 배울 내용이 아주 많을 것으로 예상된다....🥲
하지만 개발하면서 배우는게 훨씬 빠르다!!
앞으로는 개발하면서 플러터와 함께 다트에 대해 알아보자👩🏻💻
-끝-