Dart : https://dart.dev/guides/language/language-tour
- Dart 는 객체 지향 언어이다
- 함수도 객체이며 함수조차도 객체이고 모든 함수 타입의 기본 클래스인 Function 이 있다
- 이는 함수를 변수에 할당하거나 다른 함수에 인수로 전달할 수 있음을 의미한다
- Effective Dart는 public API 에 대한 타입 표시를 권장하지만 생략 가능하다
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
isNoble(atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
// 표현식이 하나인 경우 아래처럼 줄일 수 있다
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
0. The main() function
- 모든 앱에는 앱의 진입점 역할을하는 최상위 main() 함수가 있어야한다
- main() 함수는 void 를 반환하고 인수에 대한 선택적 List<String> 매개 변수를 갖는다
void main() {
querySelector('#sample_text_id')
..text = 'Click me!'
..onClick.listen(reverseText);
}
// List 파라미터가 있는 main 함수
void main(List<String> arguments) {
print(arguments);
assert(arguments.length == 2);
assert(int.parse(arguments[0]) == 1);
assert(arguments[1] == 'test');
}
여기서 잠깐 Cascade notation (..)
// 원래 코드
var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));
// cascade .. 를 적용한 코드
querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
1. Parameters
- 함수는 필수 및 선택의 두 가지 타입의 매개 변수를 가질 수 있다
- 필수 매개 변수가 먼저 나열되고 그 뒤에 선택적 매개 변수가 나열된다
1-1. Optional parameters
- 선택적 매개 변수는 이름이 지정되거나 위치가 지정 될 수 있다
Named parameters
- 함수를 호출 할 때 paramName : value 를 사용하여 매개 변수를 이름을 지정할 수 있다
- 이름이 지정된 매개 변수는 선택적 매개 변수이지만 매개 변수가 필수임을 나타 내기 위해 @required 주석을 달 수 있다
- @required 사용을 위해 package:meta meta.dart import 해야한다
/// 이름이 [bold] and [hidden] 로 지정된 매개변수를 갖는 함수
void enableFlags({bool bold, bool hidden}) {
...
}
// 함수 호출
enableFlags(bold: true, hidden: false);
/// 사용자는 child 매개 변수에 대한 값을 제공해야한다
const Scrollbar({Key key, @required Widget child})
Positional parameters
- 매개 변수를 [] 로 감싸면 선택적 positional 매개 변수로 표시된다
String say(String from, String msg, [String device]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
return result;
}
// positional 파라미터 없이 함수 호출 가능
assert(say('Bob', 'Howdy') == 'Bob says Howdy');
// 파라미터 값을 넣어서 함수 호출 시에도 가능
assert(say('Bob', 'Howdy', 'smoke signal') ==
'Bob says Howdy with a smoke signal');
Default parameter values
- 함수는 파라미터에 = 을 사용하여 named 파라미터와 positional 파라미터에 기본값을 정의할 수 있다
- 기본값은 컴파일 타임 상수여야하며 지정하지 않으면 null 이다
// Named 파라미터의 경우
/// 파라미터 [bold] 와 [hidden] 의 기본값을 각각 false 로 설정한다
void enableFlags({bool bold = false, bool hidden = false}) {...}
// 함수 호출 시 bold 에 true 를 넣으면 bold 는 true, hidden 은 false 일 것이다
enableFlags(bold: true);
// Positional 파라미터의 경우
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 을 파라미터로 전달할 수 있다
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');
}
2. Functions as first-class objects
- 함수를 다른 함수의 파라미터로 넘겨줄 수 있다
void printElement(int element) {
print(element);
}
var list = [1, 2, 3];
// printElement 함수를 파라미터로 넘긴다
list.forEach(printElement);
3. Anonymous functions
- ([Type] paramName) { ... } 형태로 익명 함수를 만들 수 있다
- 아래 예제는 forEach 내부에 익명 함수를 넘겼다
var list = ['apples', 'bananas', 'oranges'];
list.forEach((item) {
print('${list.indexOf(item)}: $item');
});
// result
0: apples
1: bananas
2: oranges
- 위 함수를 람다식으로 아래 처럼 만들 수도 있다
list.forEach(
(item) => print('${list.indexOf(item)}: $item'));
4. Lexical scope
- Dart는 변수의 범위가 코드 레이아웃에 따라 정적으로 결정된다
- 변수가 범위 내에 있는지 확인하려면 중괄호 단계로 따라가면 된다
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);
}
}
}
5. Lexical closures
- 클로저는 함수가 원래 범위 밖에서 사용되는 경우에도 Lexical scope 의 변수에 액세스 할 수있는 함수 객체이다
- 함수는 주변 범위에 정의 된 변수를 통해 닫힐 수 있다
/// 함수의 인자로 [addBy] 를 넘기면 아래 함수를 반환한다
Function makeAdder(int addBy) {
return (int i) => addBy + i;
}
void main() {
// addBy 로 2 를 넘기면 add2 에 반환된 함수가 캡쳐된다
var add2 = makeAdder(2);
// addBy 로 4 를 넘기면 add2 에 반환된 함수가 캡쳐된다
var add4 = makeAdder(4);
// 2 + 3 = 5
print(add2(3));
// 4 + 3 = 7
print(add4(3));
}
6. Testing functions for equality
- 최상위 함수, 정적 메서드, 인스턴스 메서드가 같은지 테스트하는 예제이다
void foo() {} // 최상위 함수
class A {
static void bar() {} // static 메소드
void baz() {} // 인스턴스 메소드
}
void main() {
var x;
// 최상위 함수와 비교 -> true
x = foo;
assert(foo == x);
// static 메소드와 비교 -> true
x = A.bar;
assert(A.bar == x);
// 인스턴스 메소드와 비교 -> true
var v = A(); // A 의 인스턴스 #1
var w = A(); // A 의 인스턴스 #2
var y = w;
x = w.baz;
// 이 클로저는 동일 인스턴스를 참조한다 (#2) -> true
assert(y.baz == x);
// 이 클로저는 다른 인스턴스를 참조한다 -> 같지 않으니 true
assert(v.baz != w.baz);
}
7. Return values
- 모든 함수는 값을 반환하며 반환값을 지정하지 않으면 null 을 반환한다
foo() {}
assert(foo() == null);
'기타개발 > Flutter' 카테고리의 다른 글
Dart #6 : Abstract, Implicit interface, Extends (0) | 2020.08.28 |
---|---|
Dart #5 : Classes, Constructor (0) | 2020.08.28 |
Dart #4 : if-else, for/while/do-while, switch, exceptions (0) | 2020.08.27 |
Dart #3 : Operators (0) | 2020.08.27 |
Dart #1 : Type, Collections, Final, Const etc. (0) | 2020.08.26 |
댓글