Dart Language Tour #3

t0dd·2020년 8월 31일
0

Dart Language Tour

목록 보기
3/6
post-thumbnail

Functions

Dart는 진정한 객체지향 언어이므로 함수조차도 객체이고 타입인 Function을 갖습니다. 이는 함수를 변수에 할당하거나 다른 함수에 인수로 전달할 수 있음을 의미합니다. 함수인 것처럼 Dart 클래스의 인스턴스를 호출할 수도 있습니다. 자세한 내용은 Callable 클래스를 참조하십시오.

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

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

Dart를 효율적으로 사용하기 위해서는 공용 API에 대한 타입 명시을 권장하지만 타입 명시를 생략해도 함수는 계속 작동합니다.

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

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

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

=> expr 구문은 {return expr; }. => 표기법은 때때로 화살표구문이라고도합니다.

구문이 아닌 표현식만 화살표 =>와 세미콜론 ; 사이에 나타날 수 있습니다. 예를 들어 여기에 if 문을 넣을 수 없지만 조건식을 사용할 수 있습니다.

함수는 필수 및 선택의 두 가지 유형의 매개변수를 가질 수 있습니다. 필수 매개변수가 먼저 나열되고 그 뒤에 선택적 매개변수가 나열됩니다. 선택적 매개변수는 이름이 지정되거나 위치가 지정될 수 있습니다.

일부 API (특히 Flutter 위젯 생성자)는 필수 매개변수에 대해서도 명시 된 매개변수만 사용합니다. 자세한 내용은 다음 섹션을 참조하십시오.

선택적 매개변수

선택적 매개변수는 이름 또는 위치가 될 수 있지만 둘 다는 아닙니다.

명시적 매개변수

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

enableFlags(bold: true, hidden: false);

함수를 정의할 때 {param1, param2, ...} 를 사용하여 명시적 매개변수를 지정합니다.

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

명시적 매개변수는 일종의 선택적 매개변수이지만 매개변수가 필수임을 나타내기 위해 @required로 주석을 달 수 있습니다. 사용자는 매개변수에 대한 값을 제공해야합니다. 예를 들면 :

const Scrollbar({Key key,  Widget child})

만약 자식인자를 지정하지 않고 스크롤바를 만들려고 하면 분석기가 문제를 보고합니다.

@required 주석을 사용하려면 메타 패키지에 의존하고 package: meta/meta.dart를 가져옵니다.

위치적 매개변수

함수 매개변수 세트를 []로 감싸면 선택적 위치 매개변수로 표시됩니다.

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');

매개변수의 기본 값

함수는 =를 사용하여 명시적 매개변수와 위치 매개변수 모두에 대한 기본값을 정의할 수 있습니다. 기본 값은 컴파일타임 상수여야 하며, 기본값이 제공되지 않으면 기본값은 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);
 Deprecation note: Old code might use a colon (:) instead of = to set d

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

다음 예시는 위치 매개변수의 기본값을 설정하는 방법입니다.

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');

List이나 Map을 기본값으로 전달할 수도 있습니다. 다음 예제는 list 매개변수에 대한 기본 Listgifts 매개 변수에 대한 기본 Map을 지정하는 함수 doStuff()를 정의합니다.

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() 함수

모든 앱에는 앱의 진입점 역할을하는 최상위 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 라이브러리를 사용하여 명령줄 인수를 정의하고 구문분석 할 수 있습니다.

객체로서의 함수 사용

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

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 !!!');

이 예시에서는 익명함수를 사용합니다. 다음 섹션에서 이에 대해 자세히 알아보십시오.

익명함수

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

익명 함수는 명시적 함수와 비슷합니다. 쉼표로 구분된 0개 이상의 매개변수와 괄호 사이의 선택적 유형 주석입니다.

다음 코드 블록에는 함수의 본문이 포함됩니다.

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

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

var list = ['apples', 'bananas', 'oranges'];

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

// list.forEach(
//    (item) => print('${list.indexOf(item)}: $item')
// ); 
// 함수에 명령문이 하나만 있는 경우 화살표 표기법을 사용하여 줄일 수 있습니다. 

// 출력 결과
// 0: apples
// 1: bananas
// 2: oranges

렉시컬 스코프

Dart는 Javascript 처럼 렉시컬 스코프 언어입니다. 즉, 변수의 스코프가 코드 레이아웃에 따라 정적으로 결정됩니다. 변수가 범위 내에 있는지 확인하려면 "중괄호를 바깥쪽으로" 따라갈 수 있습니다.

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

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()이 어떻게 모든 수준의 변수를 최상위 수준까지 사용할 수 있는지 확인하세요.

렉시컬 클로저

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

함수는 주변 범위에 정의 된 변수를 통해 닫힐 수 있습니다. 다음 예제에서 makeAdder()는 변수 addBy를 캡처합니다. 반환 된 함수가 가는 곳마다 addBy를 기억합니다.

/// Returns a function that adds [addBy] to the
/// function's argument.
Function makeAdder(int addBy) {
  return (int i) => addBy + i;
}

void main() {
  // Create a function that adds 2.
  var add2 = makeAdder(2);

  // Create a function that adds 4.
  var add4 = makeAdder(4);

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

동등성 테스트

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

void foo() {} // A top-level function

class A {
static void bar() {} // A static method
void baz() {} // An instance method
}

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);
}

반환 값

모든 함수는 값을 반환합니다. 반환 값을 지정하지 않으면 명령문은 null을 반환합니다. 함수 본문에 암시 적으로 추가됩니다.

foo() {}

assert(foo() == null);
profile
Javascript로 많은 것을 쉽고 빠르고 재밌게 만드는 것을 좋아합니다.

0개의 댓글