추상클래스는 다른 클래스들에게 공통된 속성과 메서드를 제공하는 클래스이다. 인스턴스를 생성 할 수 없고 메서드 또한 선언만 할 뿐 구현은 하지 않는다.
이렇게 구현하는 목적은 다양항 자식 클래스에게 공통된 동작을 제공하고 클래스의 계층 구주의 설계를 하기 위함이다.
abstract class IronMan {
var name;
var suitColor;
IronMan(this.name,this.suitColor);
// This is an abstract method. It must be implemented by subclasses.
void fly();
// This is an abstract method. It must be implemented by subclasses.
void shootLasers();
// This is an abstract method. It must be implemented by subclasses.
void withstandDamage();
}
다음과 같이 선언만 할 뿐 인스턴스나 구현된 메소드는 존재하지 않는다.
class Mark50 extends IronMan {
Mark50(String name,String suitColor) : super(name,suitColor);
void fly(){
print('$name is fly');
}
void shootLasers(){
print('$suitColor is shoot Laser!');
}
void withstandDamage(){
print('$name is make huge Damage!');
}
}
class Mark50에서 abstract class인 IronMan을 extends하여 사용할 때는 전부 @override를 통해 함수들을 재정의 해줘야 한다.
dart는 extends를 통한 다중 상속을 허용하지 않는다. 다중 상속을 하려면 class 대신 mixin을 사용해야 한다.
mixin Flyable on Animal {
void fly() {
print('I am flying!');
}
}
다음 코드의 Flyable의 의미는 반드시 Animal을 상속받는 클래스에서만 사용되어야 한다 라고 선언을 한 것이다.
class Animal {
String name;
Animal(this.name);
}
class Bird extends Animal with Flyable {
// Bird는 Animal의 모든 속성과 메소드를 가지며,
// Flyable mixin에서 제공하는 fly() 메소드도 가지고 있다.
Bird(String name) : super(name);
}
void main() {
var bird = Bird('Bird'); // "Bird"라는 이름을 가진 Bird 객체 생성
bird.fly(); // "I am flying!"을 출력합니다.
}
Bird 클래스는 Animal + mixin Flyable을 다중 상속하여 사용하고 있다.
따라서 main 함수에 객체인 bird를 사용하여 bird.fly() 함수 호출을 할 수 있게 된 것이다.
인터페이스란 클래스가 필수적으로 구현해야하는 매서드이고 일종의 규칙이나 약속이다
일반적으로 인터페이스는 클래스의 API 가운데 외부에 공개할 것들을 모아서 따로 관리하기 위한 목적으로 사용한다.
보통 다른 언어에서 인터페이스를 정의할 때는 interface, protocol 등의 키워드를 사용하고 인터페이스 내용을 구현할 때는 implements 등의 키워들를 사용한다. dart에서는 클래스와 인터페이스를 정의 할 때는 구분하지 않고 구현 할 때만 구분한다.
구체적으로 Extends로 구현하면 상속이 되고 implements로 구현하면 인터페이스가 된다.
extends != implements
extends로 상속을 하는 경우에는 클래스의 모든 내용을 재정의 할 필요는 없다.
하지만 implements로 상속을 하는 경우네는 클래스의 모든 내용을 빠짐 없이 구현해야 한다.
class IronMan {
String name;
int powerLevel;
IronMan(this.name, this.powerLevel);
void shoot() {
print('$name is shooting guns!');
}
}
다음과 같은 class가 있을 때
class IronManMK3 extends IronMan {
var flyheight;
IronManMK3(String name, int powerLevel, this.flyheight) :super(name,powerLevel);
void fly() {
print('$name is flying in $flyheight');
}
}
class IronManMK3 implements IronMan {
var flyheight;
String name = 'd';
int powerLevel = 3;
void shoot() {
print('$name is shooting guns!');
}
void fly() {
print('$name is flying in $flyheight');
}
위와 같이 implements를 사용하게 되면 부모클래스의 모든 변수 / 메소드를 재정의 해줘야 한다.