Flutter 개발을 시작하면서 내가 보려고 정리한 최소한의 Dart 문법 - 2
Null Safety
- null 값에 대한 안정성을 보장하기 위해 flutter 2.0, dart 2.12에 업데이트
- 기본값 초기화(initialize) 없이 선언하는 변수는 타입을 nullable과 non-nullable 로 구분 필요
* nullable
- 일반 타입 뒤 물음표(?)를 추가하면 해당 변수는 해당 타입 or null 이 될 수 있음을 의미
- 초기화 없이 사용시 null 값 할당
void main() {
String? name;
int? age;
bool? student;
print(name) //null
}
* non-nullable
- 물음표(?)가 없는 일반 타입은 null이 될 수 없는 값을 의미
- 사용전 초기값 할당 필요
* required
- 함수에서 named parameter나 optional parameter를 설정할 때 non-nullable로 지정하기 위해 타입 앞에 붙임
void greeting({required String name}) {
print('Hello $name!');
}
* non-nullable
- 클래스에서 non-nullable 프로퍼티가 필요하지만 디폴트 값이나 초기화를 시키지 않을 경우 나중에 값을 할당한다는 의미로 사용
class Cat {
late String name;
late int age;
}
함수의 구조
* 기본 구조
- 리턴값 타입 함수명 + (파라미터 타입 파라미터) {}
String test(String str) {
return 'test function';
}
* 화살표 함수
- JS와 달리 화살표 함수도 함수 이름 필요
- { retrun 리턴값 } 을 => 리턴값으로 축약 가능
String test(String str) => 'test function';
* 람다 함수
- 이름이 없는 익명함수 (swift, kotlin 의 클로져에 해당)
var multiply = (int a, int b) => a * b;
print(multiply(5, 6)); // Prints: 30
- 리스트에서의 사용 예시
var numbers = [1, 2, 3, 4, 5];
numbers.forEach((number) => print(number)); // Prints: 1 2 3 4 5
var squares = numbers.map((number) => number * number).toList();
print(squares); // Prints: [1, 4, 9, 16, 25]
- 정의부분과 실행부분을 분리하기 위해 람다함수를 파라미터로 넘겨주기도 함
void doSomething(Function callback) {
callback();
}
// ....
doSomething(() => print('Hello from callback!')); // Prints: Hello from callback!
Parameter
* named parameter
- 파라미터를 중괄호 ( {} ) 로 설정한 경우 이름으로 직접 파라미터를 전달 가능
void main() {
void introduce({required String name, required int age}) {
print('I am $name. $age yaers old!');
}
introduce(name: 'Sam', age: 5); //I am Sam. 5 years old!
}
* optional parameter
- 파라미터를 대괄호 ( [] ) 로 설정한 경우 선택형 인자 설정 가능
void main() {
void introduce(String name, int age, [String? food]) {
print('I am $name. $age yaers old!');
if (food is String) {
print('I like $food!');
}
}
introduce('Tom', 7); //I am Tom. 7 yaers old!
introduce('Sam', 5, 'ice cream'); //I am Sam. 5 yaers old! I like ice cream!
}
* default parameter
- = 연산자를 이용해 파라미터의 기본값 정의 가능
void main() {
void introduce(String name, int age, [String food = 'chocolate']) {
print('I am $name. $age yaers old! I like $food!');
}
introduce('Tom', 7); //I am Tom. 7 yaers old! I like chocolate!
}
객체지향 프로그래밍
- Dart는 객체지향 언어로서 클래스, 인스턴스, 상속, 추상클래스, 인터페이스, 믹스인 등을 지원
* 클래스, 인스턴스
class Person {
String name; // Field
// Constructor
Person(this.name);
// Method
void greet() {
print('Hello, I am $name');
}
}
void main() {
var john = Person('John'); // Instantiate the Person class
john.greet(); // Prints: Hello, I am John
}
* 상속
- extends를 사용하여 상속받은 클래스를 정의 가능
class Employee extends Person {
String department;
// Constructor
Employee(String name, this.department) : super(name);
// Overridden Method
@override
void greet() {
print('Hello, I am $name and I work in $department');
}
}
void main() {
var jane = Employee('Jane', 'HR'); // Instantiate the Employee class
jane.greet(); // Prints: Hello, I am Jane and I work in HR
}
* 추상 클래스
- 다른 언어처럼 추상 메소드를 선언하여 상속으로 메소드 정의 강제 가능
abstract class Shape {
double getArea(); // Abstract method
void printArea() {
print('The area is ${getArea()}');
}
}
class Circle extends Shape {
Circle(this.radius);
final double radius;
@override
double getArea() => 3.14 * radius * radius; // Concrete implementation of abstract method
}
void main() {
final circle = Circle(5);
circle.printArea(); // Prints: The area is 78.5
}
* 인터페이스
- 다른 언어와 다르게 Dart에선 인터페이스도 class로 선언
- 인터페이스로 받을땐 클래스와 달리 implements로 사용
class Printable {
void printValue() {}
}
class MyClass implements Printable {
final int value;
MyClass(this.value);
@override
void printValue() {
print('The value is $value');
}
}
void main() {
final myClass = MyClass(10);
myClass.printValue(); // Prints: The value is 10
}
* 믹스인
- class를 재사용하기 위한 문법 (가급적 상속을 피하기 위함)
- class를 상속받지 않고 클래스의 기능 이용 가능
mixin Flyable {
void fly() {
print('I can fly!');
}
}
class Animal {
void eat() {
print('I can eat!');
}
}
class Bird extends Animal with Flyable {
void chirp() {
print('I can chirp!');
}
}
void main() {
Bird bird = Bird();
bird.eat(); // Prints: I can eat!
bird.fly(); // Prints: I can fly!
bird.chirp(); // Prints: I can chirp!
}
* 캡슐화
- 다른 언어와 다르게 private가 아닌 _를 prifix로 사용
class BankAccount {
int _balance = 0; // private field
int get balance => _balance; // getter
void deposit(int amount) {
if (amount > 0) {
_balance += amount;
}
}
}
void main() {
var account = BankAccount();
account.deposit(100);
print(account.balance); // Prints: 100
}
* 다형성
abstract class Animal {
void makeNoise();
}
class Dog extends Animal {
@override
void makeNoise() {
print('Woof!');
}
}
class Cat extends Animal {
@override
void makeNoise() {
print('Meow!');
}
}
void main() {
List<Animal> animals = [Dog(), Cat()];
for (Animal animal in animals) {
animal.makeNoise();
}
}
* 예외 처리
void main() {
try {
int result = divideNumbers(10, 0);
print('The result is $result');
} catch (e) {
print('An error occurred: $e');
} finally {
print('End of try-catch');
}
}
int divideNumbers(int num1, int num2) {
if (num2 == 0) {
throw ArgumentError('You can\'t divide by zero!');
}
return num1 ~/ num2;
}
* 제네릭
// Generic Class Example
class Box<T> {
T contents;
Box(this.contents);
}
// Generic Function Example
T first<T>(List<T> items) {
return items[0];
}
void main() {
var box1 = Box<int>(10);
print(box1.contents);
var box2 = Box<String>('Hello');
print(box2.contents);
var numbers = [1, 2, 3];
print(first(numbers));
var words = ['apple', 'banana', 'cherry'];
print(first(words));
}
'Flutter' 카테고리의 다른 글
photo_manager, Error: Type 'DecoderCallback' not found 해결 (부제: flutter SDK 직접 다운로드 및 경로 설정하기) (0) | 2023.12.30 |
---|---|
[Flutter] flutter로 도넛 차트 (Donut Chart)와 데이터 라벨 구현하기 (1) | 2023.10.23 |
[Flutter] Flutter 개발을 위한 Dart 문법 총정리 - 1 (0) | 2023.07.30 |