Top

Up

함수 (Functions)

Dart는 진정한 객체 지향 언어이므로 함수도 객체이며 타입이 Function입니다. 즉, 함수를 변수에 할당하거나 다른 함수에 인수로 전달할 수 있습니다. Dart 클래스의 인스턴스를 함수처럼 호출 할 수도 있습니다. 자세한 내용은 Callable 클래스를 참조하세요.

다음은 함수 구현의 예입니다.

bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

Effective Darttype annotations for public APIs 를 권장하지만이 타입을 생략하여도 함수가 계속 작동합니다.

isNoble(atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}

표현식이 하나 뿐인 함수의 경우 약식 구문을 사용할 수 있습니다.

bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

=> 표현식 문법은{ return 표현식; }의 약식입니다. =>표기법은 때로 화살 구문(arrow syntax)이라고도 합니다.


함수는 필수 매개 변수와 선택적 매개 변수의 두 가지 유형의 매개 변수를 가질 수 있습니다. 필요한 매개 변수가 먼저 나열되고 그 뒤에 선택적 매개 변수가 나열됩니다. 명명된 선택적 매개 변수는 @required로 표시 될 수도 있습니다. 자세한 내용은 다음 섹션을 참조하십시오.

선택적 매개 변수 (Optional parameters)

선택적 매개 변수는 위치 지정 또는 이름 지정 중 하나 일 수 있지만 둘 다를 지정할 수는 없습니다.

선택적 명명 된 매개 변수 (Optional named parameters)

함수를 호출 할 때 paramName:value를 사용하여 명명된 매개변수를 지정할 수 있습니다. 예를 들면:

enableFlags(bold: true, hidden: false);

함수를 정의 할 때 {param1, param2, ...}를 사용하여 명명된 매개 변수를 지정하세요 :

/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold, bool hidden}) {...}

Flutter 인스턴스 생성 표현식은 복잡해질 수 있으므로 위젯 생성자는 명명된 매개변수를 독점적으로 사용합니다. 이렇게하면 인스턴스 작성 표현식을 읽기 쉽게 만듭니다.

@required를 사용하여 임의의 Dart 코드 (Flutter뿐 아니라)에서 명명 된 매개변수에 주석을 달아 필수 매개 변수임을 나타낼 수 있습니다. 예 :

const Scrollbar({Key key, @required Widget child})

Scrollbar가 생성 될 때, 분석기는 child 인자가 없을 때 이슈를 보고합니다.

Requiredmeta 패키지에 정의되어 있습니다. package:meta/meta.dart를 직접 가져 오거나 Flutter의package:flutter/material.dart와 같이 metaexport 하는 또 다른 패키지를 import 하세요.

선택적 위치 매개 변수 (Optional positional parameters)

[]에 함수 매개변수 세트를 래핑하면 선택적 위치 매개변수로 표시됩니다.

String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

다음은 선택적 매개변수 없이 이 함수를 호출하는 예제입니다.

assert(say('Bob', 'Howdy') == 'Bob says Howdy');

다음은 이 함수를 세 번째 매개 변수와 함께 호출하는 예제입니다.

assert(say('Bob', 'Howdy', 'smoke signal') ==
    'Bob says Howdy with a smoke signal');

매개 변수 기본 값 (Default parameter value)

함수는 = 을 사용하여 명명된 매개변수와 위치 매개변수에 대한 기본값을 정의 할 수 있습니다. 기본값은 컴파일타임 상수이어야 합니다. 기본값이 제공되지 않으면 기본값은 null입니다.

다음은 명명된 매개변수의 기본값을 설정하는 예제입니다.

/// Sets the [bold] and [hidden] flags ...
void enableFlags({bool bold = false, bool hidden = false}) {...}

// bold will be true; hidden will be false.
enableFlags(bold: true);

지원 중단 노트 :

이전 코드는 = 대신 콜론 (:)을 사용하여 명명 된 매개 변수의 기본값을 설정할 수 있습니다. 이유는 원래는 명명 된 매개 변수에 대해서만 :만이 지원 되었기 때문입니다. 이 지원은 더 이상 사용되지 않으므로 =를 사용하여 기본값을 지정하는 것이 좋습니다.

다음 예제는 위치 매개변수의 기본값을 설정하는 방법을 보여줍니다.

String say(String from, String msg,
    [String device = 'carrier pigeon', String mood]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  if (mood != null) {
    result = '$result (in a $mood mood)';
  }
  return result;
}

assert(say('Bob', 'Howdy') ==
    'Bob says Howdy with a carrier pigeon');

리스트나 맵을 기본 매개변수로 전달 할 수 있습니다. 다음 예제는 doStuff() 함수를 정의 하는데, 기본 리스트를 list 매개변수로, 기본 맵을 gifts 매개변수로 지정합니다.

void doStuff({
  List<int> list = const [1, 2, 3],
  Map<String, String> gifts = const {
    'first': 'paper',
    'second': 'cotton',
    'third': 'leather'
  }}) {
  print('list:  $list');
  print('gifts: $gifts');
}

main() 함수

모든 앱은 app의 진입점 역할을 하는 최상위 main() 함수를 가져야 합니다. main() 함수는 void를 리턴하고 인수를 위한 선택적 List<String> 매개변수를 갖습니다.

다음은 웹 앱을 위한 main() 함수의 예입니다:

void main() {
  querySelector('#sample_text_id')
    ..text = 'Click me!'
    ..onClick.listen(reverseText);
}

노트 : 위의 코드에서 ..구문은 캐스케이드이라고합니다. 캐스케이드를 사용하면 단일 객체의 멤버에 대해 여러 작업을 수행 할 수 있습니다.

다음은 인수를 취하는 명령 행 응용 프로그램을 위한 main() 함수의 예입니다 :

// Run the app like this: dart args.dart 1 test
void main(List<String> arguments) {
  print(arguments);

  assert(arguments.length == 2);
  assert(int.parse(arguments[0]) == 1);
  assert(arguments[1] == 'test');
}

args library를 사용하여 명령 줄 인수를 정의하고 구문 분석 할 수 있습니다.

일급 객체 함수 (Functions as first-class objects)

함수를 매개 변수로 다른 함수에 전달할 수 있습니다. 예:

void printElement(int element) {
  print(element);
}

var list = [1, 2, 3];

// Pass printElement as a parameter.
list.forEach(printElement);

다음과 같은 변수에 함수를 지정할 수도 있습니다.

var loudify = (msg) => '!!! ${msg.toUpperCase()} !!!';
assert(loudify('hello') == '!!! HELLO !!!');

이 예제에서는 익명의 함수를 사용합니다. 다음 섹션에서 더 자세히 설명합니다.

익명 함수 (Anonymous functions)

대부분의 함수는 main()이나 printElement()와 같이 이름이 붙어 있습니다. 익명 함수 또는 때로는 람다 또는 클로저라는 이름 없는(namedless) 함수를 만들 수도 있습니다. 익명 함수를 변수에 할당하여 컬렉션에 추가하거나 제거 할 수 있도록 할 수 있습니다.

익명 함수는 괄호 사이에 쉼표와 선택적 형식 주석으로 구분 된 0 개 이상의 매개 변수인 명명 된 함수와 유사하게 나타납니다.

다음 코드 블록에는 함수의 본문이 들어 있습니다.

 ([[Type] param1[, ]]) {
 	codeBlock;
 };  

다음 예제는 타입이 지정되지 않은 매개 변수 인 item을 사용하여 익명 함수를 정의 합니다. 리스트의 각 항목에 대해 호출 된 함수는 지정된 인덱스의 값을 포함하는 문자열을 인쇄합니다.

var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
  print('${list.indexOf(item)}: $item');
});

실행 버튼 img 를 클릭하여 다음 코드를 실행하세요.

함수에 하나의 명령문만 있으면 화살 표기법 =>을 사용하여 명령문을 단축 할 수 있습니다. DartPad에 다음 줄을 붙여 넣고 실행을 클릭하여 기능상으로 동등한 지 확인하십시오.

list.forEach(
    (item) => print('${list.indexOf(item)}: $item'));

어휘 범위 (Lexical scope)

다트는 어휘 범위가 지정된 언어입니다. 즉, 변수의 범위는 코드의 레이아웃에 의해 정적으로 결정됩니다. 변수가 범위 내에 있는지 보려면 “중괄호 밖으로 따라가면 알 수 있습니다”.

다음은 각 범위 수준에서 변수가 있는 중첩 함수의 예입니다.

bool topLevel = true;

void main() {
  var insideMain = true;

  void myFunction() {
    var insideFunction = true;

    void nestedFunction() {
      var insideNestedFunction = true;

      assert(topLevel);
      assert(insideMain);
      assert(insideFunction);
      assert(insideNestedFunction);
    }
  }
}

nestedFunction()이 최상위 수준까지 모든 수준의 변수를 사용하는 방법에 주목하십시오.

어휘 클로저 (Lexical closures)

클로저는 함수가 원래 범위 외부에서 사용되는 경우에도 어휘 범위의 변수에 액세스 할 수 있는 함수 객체입니다.

함수는 주변 범위에 정의 된 변수를 닫을 수 있습니다. 다음 예제에서, makeAdder()는 변수 addBy를 캡쳐합니다. 반환 된 함수가 어디에서든지 addBy를 기억합니다.

/// 함수의 인수에 [addBy]를 더하는 함수를 반환합니다.
Function makeAdder(num addBy) {
  return (num i) => addBy + i;
}

void main() {
  // 2를 더하는 함수를 만듭니다.
  var add2 = makeAdder(2);

  // 4를 더하는 함수를 만듭니다.
  var add4 = makeAdder(4);

  assert(add2(3) == 5);
  assert(add4(3) == 7);
}

함수 항등성 테스트 (Testing functions for equality)

다음은 최상위 함수, 정적 메서드 및 인스턴스 메소드가 같은지 테스트하는 예제입니다.

void foo() {} // 최상위 함수

class A {
  static void bar() {} // 정적 메서드
  void baz() {} // 인스턴스 메서드
}

void main() {
  var x;

  // 최상위 함수 비교
  x = foo;
  assert(foo == x);

  // 정적 메서드 비교.
  x = A.bar;
  assert(A.bar == x);

  // 인스턴스 메서드 비교
  var v = A(); // Instance #1 of A
  var w = A(); // Instance #2 of A
  var y = w;
  x = w.baz;

  // 이러한 클로저는 동일한 인스턴스 (#2)를 참조하므로 동일합니다.
  assert(y.baz == x);

  // 이러한 클로저는 서로 다른 인스턴스를 참조하므로 동일하지 않습니다.
  assert(v.baz != w.baz);
}

반환값 (Return values)

모든 함수는 값을 반환합니다. 리턴 값이 지정되지 않으면 return null;문이 암시적으로 함수 본문에 추가됩니다.

foo() {}

assert(foo() == null);

이전: 내장 타입 (Built in types)

다음: 연산자 (Operators)

문서 변경 이력

2019년 5월 15일: 첫 작성.