4.0 Defining a Function
Dart는 객체 지향 언어이기 때문에 함수도 객체이며, 타입은 Function입니다. 이를 통해 함수를 변수에 할당하거나 다른 함수의 인수로 전달할 수 있습니다. Dart에서는 함수 선언을 여러 방식으로 할 수 있습니다.
1. 기본적인 함수 선언
String sayHello(String name) {
return "Hello ${name}, nice to meet you.";
}
num plus(num a, num b) {
return a + b;
}
2. Fat Arrow Syntax(=>)
Fat arrow syntax는 하나의 표현식만 포함하는 함수에서 사용할 수 있는 단축 구문입니다. 함수의 본문을 한 줄로 표현할 때 사용되며, 표현식의 결과가 함수의 반환값이 됩니다.
// 일반 함수 선언을 fat arrow syntax로 변환
String sayHello(String name) => "Hello ${name}, nice to meet you.";
num plus(num a, num b) => a + b;
=>
는return
을 의미하는 역할을 합니다. 즉,=>
뒤의 표현식이 바로 반환됩니다.- 본문이 단 한 줄일 때만 사용 가능하며, 여러 줄이 필요하다면
{}
블록을 사용해야 합니다.
3.함수 사용 예시
void main() {
print(sayHello("sugar")); // 출력: Hello sugar, nice to meet you.
print(plus(5, 10)); // 출력: 15
}
Fat Arrow Syntax의 장점
- 간결함: 함수가 짧고 단순할 때 사용하면 코드가 훨씬 간결해집니다.
- 가독성: 한 줄로 표현된 함수는 더 직관적으로 읽히기 때문에 가독성이 좋습니다.
주의 사항
- Fat arrow syntax는 하나의 표현식만 포함할 수 있습니다. 여러 줄의 로직이 필요한 함수는 블록(
{}
)을 사용해야 합니다.
4.1 Named Parameters (Named Arguments)
Dart에서는 함수의 매개변수를 더 명확하고 유연하게 다루기 위해 Named Parameters를 지원합니다. 이는 특히 함수 호출 시 매개변수의 순서를 잊거나, 어떤 값이 어떤 매개변수를 의미하는지 헷갈릴 때 매우 유용합니다.
1. 기본 함수 선언 문제점
String sayHello(String name, int age, String country) {
return "Hello $name, you are $age, and you come from $country";
}
void main() {
print(sayHello('nico', 19, 'cuba'));
}
- 위 코드는 매개변수가 순서에 의존합니다. 사용자가 순서를 잊거나 인자가 뜻하는 것이 무엇인지 헷갈릴 수 있습니다.
2. Named Parameters를 사용하여 해결
Named Parameters를 사용하면 함수 호출 시 매개변수의 이름을 명시적으로 지정할 수 있어, 순서에 상관없이 이해하기 쉬운 코드를 작성할 수 있습니다.
String sayHello({String name, int age, String country}) {
return "Hello $name, you are $age, and you come from $country";
}
void main() {
print(sayHello(
age: 12,
name: 'nico',
country: 'cuba',
));
}
- 중괄호({}) 를 사용하여 매개변수를
named parameters
로 만들 수 있습니다. - 함수를 호출할 때 매개변수의 이름과 값을 함께 입력하므로, 순서를 지키지 않아도 됩니다.
3. Null Safety 문제 해결 방법
Dart는 null safety를 적용하므로, named parameters 중 하나가 null일 경우 문제가 발생할 수 있습니다. 이를 해결하는 두 가지 방법이 있습니다.
3.1 Default Value 지정
매개변수에 기본값을 지정하여, 값이 전달되지 않았을 때도 안전하게 처리할 수 있습니다.
String sayHello({
String name = 'anon',
int age = 99,
String country = 'wakanda',
}) {
return "Hello $name, you are $age, and you come from $country";
}
void main() {
print(sayHello()); // 매개변수를 전달하지 않아도 기본값이 사용됨
}
- 기본값을 지정하면, 함수 호출 시 인수를 생략해도 default value가 사용됩니다.
3.2 Required Modifier 사용
required
* 키워드를 사용하여 매개변수가 반드시 전달되어야 한다고 지정할 수 있습니다.
String sayHello({
required String name,
required int age,
required String country,
}) {
return "Hello $name, you are $age, and you come from $country";
}
void main() {
// print(sayHello()); // 컴파일 오류 발생 (required 매개변수가 없으므로)
print(sayHello(
name: 'jisoung',
age: 17,
country: 'korea',
)); // 올바른 호출
}
required
를 사용하면 해당 매개변수는 반드시 값이 있어야 하며, 그렇지 않으면 컴파일 에러가 발생합니다.
4. 잘못된 코드 예시와 Named Parameters로 해결
문제: 인수의 의미를 쉽게 알 수 없음
String sayHello({
required String name,
required int age,
required String country,
}) {
return "Hello $name, age: $age, country: $country";
}
void main() {
print(sayHello(
name: "jisoung",
age: 17,
country: "korea",
));
}
Named Parameters
를 사용하면 함수 호출 시 인수의 의미를 명확히 알 수 있어 가독성이 높아집니다.5. 정리- Named Parameters를 사용하면 매개변수의 순서를 지키지 않아도 되며, 매개변수의 의미를 명확히 할 수 있습니다.
- Default Value나 required 키워드를 통해 null safety를 보장할 수 있습니다.
- 이를 통해 코드의 가독성을 높이고, 더 안전한 함수 호출이 가능합니다.
4.2 Optional Positional Parameters
Dart에서는 []
를 사용하여 Optional Positional Parameters(옵셔널 위치 매개변수) 를 정의할 수 있습니다. 이때 매개변수는 선택적으로 제공될 수 있으며, 함수를 호출할 때 반드시 값을 전달하지 않아도 됩니다.
1. 기본 개념
- name과 age는 필수 매개변수로 함수가 호출될 때 반드시 값을 전달해야 합니다.
- country는 Optional Positional Parameter로, 제공하지 않으면 기본값을 사용하거나 생략할 수 있습니다.
2. 코드 예시
String sayHello(String name, int age, [String? country = ""]) {
return 'Hello ${name}, You are ${age} from the ${country}';
}
void main() {
var result = sayHello("sugar", 10); // country 생략 가능
print(result); // 출력: Hello sugar, You are 10 from the
}
[String? country = ""]
: 대괄호([]
) 안에 작성된 매개변수는 Optional Positional Parameter로, 제공되지 않으면 기본값""
가 사용됩니다.- Optional 매개변수를 생략할 수 있기 때문에,
sayHello("sugar", 10)
와 같이 호출할 수 있습니다.3. Optional Positional Parameters의 특징 - 매개변수의 순서를 반드시 지켜야 합니다.
- 선택적 매개변수는 필수 매개변수 뒤에 위치해야 합니다.
- 기본값을 설정하지 않으면, 생략된 경우 해당 매개변수는 null이 됩니다.
여기서String sayHello(String name, int age, [String? country]) { return 'Hello ${name}, You are ${age} from the ${country ?? 'nowhere'}'; }
??
연산자는 null인 경우 기본값'nowhere'
를 사용할 수 있게 합니다.
4.3 QQ Operator
Dart의 QQ Operator (Null-aware Operator)
Dart에서는 Null-safety를 위해 QQ Operator(Null-aware Operator)를 자주 사용합니다. 이를 통해 null 값이 발생할 때 대체 값을 쉽게 지정할 수 있으며, 코드의 가독성을 높여줍니다.
1. Null-safe 코드 작성
다음 코드는 null 값을 허용하지 않기 때문에 오류가 발생할 수 있습니다.
String upperName(String name) => name.toUpperCase();
void main() {
upperName('jisoung');
upperName(null); // Error 발생!
}
2. 전통적인 null 체크 방식
null 값을 허용하고, null이 아닐 경우에만 특정 작업을 수행하는 코드를 작성할 수 있습니다.
String upperName(String? name) {
if (name != null) {
return name.toUpperCase();
}
return 'NONE';
}
3. 삼항 연산자로 코드 간결화
위 코드를 삼항 연산자를 사용하여 더 짧게 쓸 수 있습니다.
String upperName(String? name) => name != null ? name.toUpperCase() : "NONE";
4. QQ Operator로 더 간결하게 작성
Dart에서는 ??
(Null-coalescing operator) 를 사용하여 코드를 더 짧고 간결하게 작성할 수 있습니다.
String upperName(String? name) => name?.toUpperCase() ?? "NONE";
?.
: null일 수 있는 객체에 접근할 때 사용됩니다. null이 아닐 때만 메서드를 호출하고, null일 경우 null을 반환합니다.??
: 왼쪽 값이 null이면 오른쪽 값을 반환합니다.5. QQ Equal (??=) Operator??=
*는 변수에 값이 없을 때만 값을 할당하는 연산자입니다.
void main() {
String? name;
// 만약 name이 null이면 'jisoung'을 할당
name ??= 'jisoung';
print(name); // 출력: jisoung
}
??=
: 왼쪽의 값이 null이면 오른쪽 값을 할당합니다.
6. 정리
?.
: null일 수 있는 객체에 안전하게 접근할 때 사용합니다.??
: 왼쪽 값이 null일 경우 오른쪽 값을 반환합니다.??=
: 값이 null일 때만 변수를 할당할 때 사용됩니다.
4.4 Typedef
Dart에서 typedef는 자료형에 사용자가 원하는 별명(alias)을 붙일 수 있는 기능입니다. 이를 통해 복잡한 타입을 더 간단한 이름으로 정의하거나, 특정 자료형에 대한 별명을 만들어 코드의 가독성을 높일 수 있습니다.
1. Typedef의 기본 사용법
typedef를 사용하여 자료형에 새로운 별명을 정의할 수 있습니다. 아래는 리스트(List)의 별명을 ListOfInts로 정의하는 예시입니다.
typedef ListOfInts = List<int>;
ListOfInts reverseListOfNumbers(ListOfInts list) {
var reversedList = list.reversed.toList();
return reversedList;
}
typedef ListOfInts = List<int>;
:List<int>
타입을 ListOfInts라는 별명으로 정의했습니다.- 이를 통해
List<int>
를 더 간결하게 ListOfInts로 표현할 수 있습니다.
2. Typedef의 장점
- 코드 가독성 향상: 복잡한 타입을 짧고 명확한 별명으로 정의할 수 있어 가독성이 향상됩니다.
- 유지보수 용이: 코드 변경 시 여러 곳에서 사용된 자료형을 쉽게 관리할 수 있습니다.
3. 함수 타입에 대한 typedef 사용
typedef는 함수의 시그니처에 대한 별명을 정의하는 데도 사용할 수 있습니다. 예를 들어, 특정 함수 타입을 별명으로 정의하면, 동일한 함수 타입을 여러 곳에서 간결하게 사용할 수 있습니다.
typedef IntOperation = int Function(int, int);
int add(int a, int b) => a + b;
void main() {
IntOperation operation = add;
print(operation(2, 3)); // 출력: 5
}
typedef IntOperation = int Function(int, int);
: 두 개의 int
를 받아 int
를 반환하는 함수 타입에 IntOperation이라는 별명을 부여했습니다.
'개발자 > SupaBase && Flutter' 카테고리의 다른 글
06. (Dart 개념_노마드코더 강의)설계도에 빗댄 Dart 개념 총정리 (2) | 2024.10.23 |
---|---|
05. (Dart 개념_노마드코더 강의)Classes (0) | 2024.10.23 |
03. (Dart 개념_노마드코더 강의) Data Type (1) | 2024.10.23 |
02. (Dart 개념_노마드코더 강의) Variables (1) | 2024.10.23 |
01. (Dart 개념_노마드코더 강의) Flutter가 Dart를 선택한 이유 (0) | 2024.10.23 |