[Dart] 3. Functions 함수

yunulog·2023년 1월 2일
0

Dart

목록 보기
3/5
post-thumbnail

3. FUNCTIONS

0. Defining a Function

함수를 정의할 때에는 main 함수 안에 있을 필요는 없다.

함수를 정의할 때 크게 두가지로 나뉘는데 return을 할때와 안할때이다.

void sayHello(String name) {
  print("Hello $name 만나서 반가워");
}

void main() {
	//...
}

위와 같이 return을 하지 않고 단순히 출력만 하는 함수의 경우에는 함수 이름 앞에 void 를 붙여서 만들어준다.

void 는 이 함수가 아무것도 return하지 않는다는 의미이다.

그렇다면 main 함수 앞에 void 가 붙는 이유도 설명된다.
main 함수는 무언가를 return 하는 함수가 아니다.
단지 그 안에 들어있는 이벤트들을 실행해 줄 뿐이다.

무언가를 return 하기 위해서는 다음과 같이 return 할 데이터 타입을 명시해주어야 한다

String sayHello (String name) {
  return "Hello $name 만나서 반가워";
}

void main() {
  print(sayHello('yunu'));
	// Hello yunu 만나서 반가워
}

fat arrow syntax (=>)

그런데 위와 같이 별다른 명령 없이 바로 return 하는 함수의 경우에는
return과 중괄호를 없애고 화살표 (=>)를 이용해서 함수를 만들 수 있다.
fat arrow syntax (=>)는 곧바로 return 한다는 의미다.

String sayHello (String name) => "Hello $name 만나서 반가워";

void main() {
  print(sayHello('yunu'));
	// Hello yunu 만나서 반가워
}

물론 이 방법은 곧바로 return 하는 경우에만 사용할 수 있다.



1. Named Parameters

Dart에서는 다음과 같이 여러가지 데이터를 함수에 넣어서 만들 수 있다.

String sayHello (String name, int age, String country) {
  return "Hello $name, you are $age, and you came from $country";
}

void main() {
  print(sayHello('yunu', 23, "south Korea"));
	// Hello yunu, you are 23, and you came from south Korea
}

하지만 sayHello('yunu', 23, "south Korea") 처럼 데이터들을 쭉 나열해서 사용하면
사용자가 순서를 헷갈릴 수도 있고, 처음 보는 사람은 이게 뭔가 싶을 수 있다.

named argument

이 때 named argument 를 사용해줄 수 있다.

named argument 를 사용할 때에는 다음과 같이 해준다.

  1. 함수를 만들 때 데이터를 명시하는 부분에서 중괄호를 추가해준다.
    String sayHello (String name, int age, String country)
    String sayHello ({String name, int age, String country})
  2. 데이터의 디폴트값을 정해준다.
    Dart는 null safety가 설정되어 있기 때문에 사용자가 데이터를 입력하지 않을 경우를 대비한다.
    그래서 디폴트값을 정해주지 않으면 빨간줄이 그어지면서 오류가 뜬다.
    String sayHello (String name, int age, String country)
    String sayHello ({String name = 'haha', int age = 20, String country = 'America'})
  3. 함수를 사용할 때 데이터 이름을 명시해준다.
    이 때, 순서가 뒤바껴도 상관이 없다!
    sayHello('yunu', 23, "south Korea")
    sayHello(age: 23, country: 'South Korea', name: 'yunu')

<전체 코드>

String sayHello ({String name = 'haha', int age = 20, String country = 'America'}) {
  return "Hello $name, you are $age, and you came from $country";
}

void main() {
  print(sayHello(
    age: 23,
    country: 'South Korea',
    name: 'yunu'
  ));
	// Hello yunu, you are 23, and you came from South Korea

	print(sayHello(
    country: 'South Korea',
  ));
	// Hello haha, you are 20, and you came from South Korea
	// 데이터를 입력하지 않은 name과 age는 설정해둔 디폴트값으로 출력됨
}

required

만약 named argument를 사용하면서 디폴트값을 정해주고싶지 않다면 어떻게 해야할까?
즉, 값을 직접 사용자로부터 받아오고 싶다면?

이 때 required 를 사용할 수 있다.

사용법은 간단하다.
설정되어있던 디폴트값을 모두 지워주고 데이터 타입 앞에 required만 붙여주면 된다.

required를 사용할때는 함수를 쓸 때 데이터를 생략하는 것은 허용되지 않는다.
반드시 데이터에 값을 넣어서 함수를 사용하도록 한다.



2. Optional Positional Parameters

Positional Parameters 는 함수를 사용할 때 참조값을 순서대로 넣어줘야한다는 의미이다.

String sayHello (String name, int age, String country) {
  return "Hello $name, you are $age, and you came from $country";
}

void main() {
  print(sayHello('nana', 12, 'japan'));
}

이런식으로 Positional Parameters 를 사용할 때에는 참조값이 하나라도 빠지면 에러가 뜬다.

하지만 optional 하게 Positional Parameters 를 사용하려면 다음과 같이 하면 된다.

  1. 함수를 만들 때 데이터를 대괄호로 묶어주고,
    String country[String country]

  2. 데이터타입 뒤에 물음표(?)를 붙여 nullable하게 만들어 준 다음,
    [String country][String? country]

  3. 디폴트 값을 설정해준다.
    [String? country][String? country = 'japan']

String sayHello (String name, int age, [String? country = 'japan']) => 
  "Hello $name, you are $age, and you came from $country";

void main() {
  var result = sayHello('nana', 12);
  print(result);
	// Hello nana, you are 12, and you came from japan
}

이렇게 하면 country 데이터를 입력하지 않아도 디폴트값인 ‘japan’이 출력된다.



3. QQ Operator

이름을 대문자로 바꿔서 return 하는 함수를 만들어보자

String capitalizeName(String name) => name.toUpperCase();

void main() {
  capitalizeName('john');
}

이 함수에 null 값을 넣을 수 있게 해보자.

우선 String 뒤에 물음표를 붙여 nullable하게 만들어주고
null 값에는 toUpperCase 함수를 쓸 수 없으므로 조건문을 만들어준다.

String capitalizeName(String? name) {
  if (name != null) {
    return name.toUpperCase();
  }
  return 'NULL';
}

이걸 fat arrow(=>)를 이용해서 더 짧게 만들어주자.

String capitalizeName(String? name) => name != null ? name.toUpperCase() : 'NULL';

이걸 더 짧게 만들면?

여기서 QQ Operator 가 나온다.

QQ Operator
좌항 ?? 우항
좌항이 null 값일 경우 우항을 적용한다.

String capitalizeName(String? name) => name?.toUpperCase() ?? 'NULL';

name?.toUpperCase()null 값일 경우 ‘NULL’이라는 데이터를 반환할 것이다.
(name 뒤에 물음표는 name을 nullable 하게 만들기 위해 붙인 것이다.)

**QQ Equals (QQ Assignment Opertor)
데이터 ??= ‘값’;
데이터가 null 값일 경우 오른쪽 값을 넣어준다.

void main() {
  String? name;
  name ??= 'noon';
  print(name);
	// noon
}

name이라는 데이터가 선언됐지만 null값이므로 ‘noon’이 name 에 할당된다.



4. Typedef

List 의 요소 배열을 뒤집어서 return 하는 함수를 만들어보았다.

List<int> reverseListOfNumbers(List<int> list) {
  var reversed = list.reversed;
  return reversed.toList();
}

보면 List<int> 라는 코드가 여러번 쓰인다.

이를 typedef를 이용해 변수에 담아서 다음처럼 List<int> 대신 사용할 수 있다..

typedef ListOfInts = List<int>;

ListOfInts reverseListOfNumbers(ListOfInts list) {
  var reversed = list.reversed;
  return reversed.toList();
}

물론 Map의 경우에도 typedef를 이용할 수 있지만
Map처럼 구조화된 데이터의 경우에는 class를 이용하는 것이 더 적절하다.

Class는 다음 게시글에서 다룬다.

<참조>

[노마드 코더] Dart 강좌

0개의 댓글