순한맛 12 플러터 다트(dart) 핵심정리: 클래스와 위젯의 정체 1
예시) 스마트폰
스마트폰을 만들려면 설계도가 필요
> 어느 곳에 어떤 부품이 들어가야 하면 어떤 기능이 들어가야할지 정확하게 설계되어야 함.
> 이러한 설계도를 바탕으로 수천대의 스마트폰을 만듦 > 하지만 같은 설계도와 공정으로 만들어진 스마트폰이 완벽하게 모두 똑같은 것이라고 할 수 있는가?
> 정답은 No. 스마트폰별로 시리얼 번호가 모두 다르고, 그 안의 부품들의 시리얼 번호 또한 모두 다름. 또한 사용하는 유심도 모두 다름. 같은 스마트폰이지만 각각의 구분이 가능한 스마트폰으로 존재
- 객체 : 현실 세계에서 만지고 느낄수 있는 것. 예) 차, 사람, 감정 등
- 속성 : 객체를 이루는 것. 예) 눈, 코, 입
- 기능 : 객체가 행동하는 행위예) 말하기, 듣기 ,걷기 등
- 클래스 : 객체의 대한 속성과 기능이 정의되어 있음. ( = 스마트폰 설계도)
1) 속성 : 액정, 카메라 무듈, 홈버튼, 스크린
2) 기능 : 전화걸기, 사진찍기, 인터넷 검색
- 인스턴스 : Class의 속성, 기능으로 만들어진 것. ( = 설계도대로 만들어진 스마트폰)
(이 때 같은 설계도(클래스)로 만들어져서 같은 속성과 기능을 가지는 스마트폰(인스턴트)이지만 각자 고유의 시리얼넘버로 구분이 가능하다.)
객체 : 메모리의 할당되어진 순간의 Class.
인스턴스 : 할당되어진 Class 기반으로 객체가 코드상으로 새롭게 만들어진 것.
Class and Widget
▪ 프로그래밍 상에서의 클래스
- 객체가 가져야하는 속성과 기능을 저의한 내용을 담고 있는 설계도 역할
▪ 프로그래밍 상에서의 객체
- 클래스가 정의된 후 메모리상에 할당되었을 때 이를 객체라고 함
▪ 프로그래밍 상에서의 인스턴스
- 클래스를 기반으로 생성 됨
- 클래스의 속성과 기능을 똑같이 가지고 프로그래밍 상에서 사용되는 대상
(* 스마트폰 예시 추가
클래스로부터 객체를 만드는 과정을 클래스의 인스턴스화, 어떤 클래스로부터 만들어진 객체를 해당 클래스의 인스턴스라고함.
인스턴스는 객체와 같은 의미지만, 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 가지고 있으며, 인스턴스는 어떤 클래스로부터 만들어진 것이지를 강조하는, 보다 구체적인 의미를 가짐.
그래서 스마트폰 예시에서 '스마트폰은 인스턴트다' 보다는 '스마트폰은 객체다',
'스마트폰은 스마트폰 클래스의 객체다' 보다 '스마트폰은 스마트폰 클래스의 인스턴스다' 라고하는 것이 더 자연스러움)
스마트폰 설계도 제품
---------------------->
클래스 인스턴스화 인스턴스(객체)
다트를 연습해볼 수 있는 DartPad
DartPad
dartpad.dev
class Person{ //클래스명은 대문자로 시작
String name = 'John';
int age;
String sex;
}
void main(){
Person p1 = new Person(); //인스턴스 생성
// 해석 : Person 클래스로 p1 이름을 가진 인스턴스 생성
p1.age = 30;
print(p1.age);
}
주의* int age, String sex와 같이 초기값 없이 변수 생성만 하면 다음과 같은 에러가 발생.
non-nullable instance field must be initialized
Dart 는 Null Safety에 대한 규칙을 가지고 있음
Null Safety : 개발되는 코드가 Null 안전성을 보장한 상태로 개발되게 하고자 하는 개념
- Nullable 과 Non-Nullable 의 구분해서 선언해주어야 함.
이는 컴파일러에게 이 변수에 null 이 대입이 될수 있는지 될수 없는지를 명확하게 알려주자는 개념
이렇게 컴파일러에게 정보를 주면 컴파일러가 알아서 Non-Nullable 변수에 null 이 대입되는 상황의 에러를 발생시켜 주거나, Nullable 변수를 NPE 를 고려하지 않고 작성하는 상황을 에러를 발생시켜 주게 된다.
규칙 1) Non-Nullable 변수는 선언과 동시에 초기값
- Non-Nullable이라면 변수 선언 시 초기값 필수.
- ? 를 이용해 Nullable 선언.
int a1;//error
int? a2;
규칙 2) var 타입에서의 Null Safety
- var 로 변수선언하면 타입 유추(type inferred). 즉, 대입되는 값에 의해 타입이 결정
> 이 때는 ? 추가할 수 없음
var a1=10;
var a2=null;
var a3;
var? a4=null;//error
규칙 3) dynamic 타입에서의 Null Safety
- dynamic 타입이 대입되는 값을 한정하지 않겠다는 의미이며 모든 타입의 데이터가 대입될수 있다는 의미이기에 ? 가 추가되어 선언될수 있지만 의미가 없다.
dynamic a1 = 10;
dynamic a2;
dynamic? a3;
testFun() {
a1=null;
a2=null;
a3=null;
}
규칙 4) Local Variable 에서만 Non-Nullable 변수가 선언과 동시에 초기화 되지 않아도 됨.
int a1;//error
class User {
int a1;//error
}
testFun() {
int a1;
a1=null;//error
}
규칙 5) casting Test
- 타입적으로 Nullable 변수는 Non-Nullable 변수의 상위 타입이다. 즉 int? 타입이 int 타입의 상위 타입이 된다.
그럼으로 Non-Nullable 변수가 Nullable 에 대입되는 것은 스마트 캐스팅에 의해 자동으로 형변형이 된다.
하지만 Nullable 변수가 Non-Nullable 에 대입되는 것은 에러이며 하고자 한다면 명시적 캐스팅을 사용해 주어야 한다.
Dart 에서 명시적 캐스팅 연산자는 as 이다.
int a1=10;
int? a2=10;
main() {
a1=a2;//error
a2=a1;//ok
}
> a1 은 Non-Nullable로 선언되어 있으며 a2 는 Nullable로 선언되어 있음.
> a2 가 a1 에대입될 때 에러 발생. 그래서 명시적 캐스팅 필요
int a1=10;
int? a2=20;
main() {
a1=a2 as int;//ok
print("a1: $a1, a2: $a2");//a1: 20, a2: 20
}
Null Safety 연산자
1) !
- null check operator — runtime error throw
어떤 변수 뒤에 ! 을 추가하면 이 변수 값이 null 인 경우 runtime error 발생
int? a2=20;
main() {
a2!;
a2=null;
a2!;
}
> 마지막 라인에서 런타임 에러 발생
2) ?. ?[ ] ?.. — null aware operator
- 객체의 값이 null 이 아닌경우 멤버에 접근하며 null 이면 멤버 접근 없이 null 을 값을 발생시키는 연산자.
main() {
int? no1=10;
bool? result1 = no1?.isEven;
print('result 1 : $result1');//true
no1=null;
bool? result2 = no1?.isEven;
print('result 2 : $result2');//null
}
> nullable 로 선언된 객체들은 객체의 멤버 접근시 ?. 을 이용해 null safety 하게 코드가 작성되게 강제됨
3) late
- 변수가 null 인 상태로 이용되지는 않지만 초기값이 앱이 실행되면서 결정되는 경우, 단어 뜻 그대로 초기화 시점을 뒤로 미루겠다는 의미
int a1;//compile error
late int a2;//ok
(* 연산자는 late 외에는 공부와 이해가 더 필요)
출처 :깡샘의 토마토 Flutter 2.0 -Null Safety https://kkangsnote.tistory.com/98
위의 Null Safety를 바탕으로 에러가 나지 않으려면 제일 간단한 방법은 ? / late
class Person{
String name = 'John';
int? age; // ? 추가
late String sex; // late 추가
}
void main(){
Person p1 = new Person();
p1.age = 30;
print(p1.age);
}
순한맛 13 플러터 다트(dart) 핵심정리: 클래스와 위젯의 정체 2
생성자와 관련된 함수의 구조와 기능
생성자의 구조와 역할
클래스와 위젯의 관계
생성자
- 함수의 모양을 하고 있음
addNumber(int num1, int num2){ //
return num1 + num2;
}
void main() {
print(addNumber(3, 4));
}
> Dart 는 타입 추론 언어. 타입 표시하지 않아도 에러 안뜸
- 생성자는 인스턴스 생성함과 동시에 클래스에서 정의한 변수값을 할당 받도록 강제함
> 우리가 가진 인스턴스가 착오없이 만들어지도록 도와주는 역할
class Person {
String? name;
int? age;
late String sex;
//생성자
//인스턴스가 만들어질 때 딱 1번만 호출됨
Person(String name, int age, String sex){
//생성자에 argument 입력 = 인스턴스 생성시 반드시 3개의 argument 입력 받아야함
this.name = name;
this.age = age;
this.sex = sex;
// this를 이용해서 들어온 변수값을 멤버 변수에 할당해 줌
}
}
void main() {
Person p1 = new Person('Tom', 30, 'm');
Person p2 = new Person('Suzy', 27, 'f');
print(p1.age);
print(p2.age);
}
named argument
- 생성자의 argument가 여러 개일 때, 그중 일부만 값을 입력받고 싶을 때
> 생성자 내 argument를 {} 중괄호로 묶어줌
But 여기서 또 에러가 뜸..
the parameter 'name' can't have a value of 'null' because of its type, but the implicit default value is 'null'
왜 또... 도대체 뭐가 문제니...
DartPad에서 강의와 다른 점은 Install SDK 뿐이라 이걸 설치하기로..
- Dart SDK 설치
0. Chocolatey 가 설치되어 있지 않은 상태라면 설치
(Chocolatey : 윈도우용 패키지 매니저) 아래 블로그 참조
CHOCOLATEY 윈도우 패키지 매니저 설치하기 - 초콜라티
CHOCOLATEY란? 윈도우에서 각종 프로그램을 설치하다 보면 Chocolatey - 초콜라티 - 를 사용해서 설치하라는 지시를 종종 볼 수 있습니다. 그럼 Chocolatey 란 무엇이나? 윈도우용 패키지 매니저 입니다.
digiconfactory.tistory.com
1. CMD 관리자 권한으로 실행 > choco install dart-sdk 입력
2. 새 CMD 띄워서 dart --version 로 SDK 설치 된 것 확인
하지만 그래도 여전한 에러
Null Safety 때문인가 싶어서 생성자 내 argument 타입에도 똑같이 처리
void main() {
Person p1 = new Person(age:30);
Person p2 = new Person();
print(p1.age);
print(p2.age);
}
Widget은 Class를 통해서 생성된 인스턴스.
named argument를 이용해서 필요한 것만 선별적으로 골라 사용했음.
순한맛 14 앱바(app bar) 메뉴 아이콘 추가하기
app bar 메뉴 아이콘 추가하기
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Appbar',
theme: ThemeData(
primarySwatch: Colors.red
),
home: MyPage(),
);
}
}
class MyPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Appbar icon menu'),
centerTitle: true,
elevation: 0.0,
leading: IconButton( // leading : 간단한 타이틀들을 앱바 왼쪽에 위치시키는 기능
icon: Icon(Icons.menu),
onPressed: () { // Button은 액션이 있어야함
print('menu button is clicked');
},
) ,
actions: <Widget>[
IconButton( // leading : 간단한 타이틀들을 앱바 왼쪽에 위치시키는 기능
icon: Icon(Icons.shopping_cart),
onPressed: () { // Button은 액션이 있어야함
print('shopping_cart button is clicked');
},
) ,
IconButton( // leading : 간단한 타이틀들을 앱바 왼쪽에 위치시키는 기능
icon: Icon(Icons.search),
onPressed: () { // Button은 액션이 있어야함
print('search button is clicked');
},
) ,
],
),
);
}
}
App bar icon button
- leading : 아이콘 버튼이나 간단한 위젯을 왼쪽에 배치할 때
- actions : 복수의 아이콘 버튼 등을 오른쪽에 배치할 때
- onPressed : 함수의 형태로 일반 버튼이나 아이콘 버튼을 터치했을 때 일어나는 이벤트를 정의하는 곳
'공부 > Flutter' 카테고리의 다른 글
flutter 이미지/에셋 추가 시 생기는 Unable to load asset 오류 해결 (안드로이드 스튜디오) (2) | 2023.01.25 |
---|---|
Flutter 스터디 5 Drawer 메뉴 (0) | 2023.01.25 |
Flutter 스터디 3 캐릭터 카드 페이지 만들기 (+ Layout 몇 개 정리) (0) | 2023.01.16 |
Flutter 스터디 2 Widget과 main.dart 기본 작성 (0) | 2023.01.16 |
[미해결] Flutter 설치 시 오류) 비주얼스튜디오 microsoft.net.4.8.fullRedist를 설치할 수 없습니다. (1) | 2023.01.16 |