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
매개변수에 대한 기본 List과 gifts
매개 변수에 대한 기본 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()
함수는 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);