<자바의 클래스>
public class Circle{
int radius; //반지름 필드
String name; //이름 필드
public Circle(){} //생성자 메소드
public double getArea(){ //면적 메소드
return 3.14*radius*radius;
}
}
public static void main(String args[]){
Circle pizza; //Circle객체의 레퍼런스변수 선언
pizza=new Circle();
pizza.radius=10;
pizza.name="인생피자";
double area=pizza.getArea();
}
typedef
- 자료형에 alias를 설정하는 방법
- 주로 integer List나 Map,Set과 같이 간단한 것들에 쓴다.
typedef ListOfInt = List<int>;
ListOfInt reverseList(ListOfInt list){
var reversed=list.reversed;
return reversed.toList();
}
void main(){
print(reverseList([1,2,3]));
}
typedef UserInfo = Map<String,String>;
String sayHi(UserInfo userInfo){
return "Hi ${userInfo['name']}";
}
void main(){
print(sayHi({'name':'su'})); //Hi su
}
<다트의 클래스>
class Player{
String name='nico';
final int xp=500;
void sayHello() => print("Hi this is $name");
}
void main(){
var player=Player(); //new 안붙여도됌
player.sayHello();
}
→ 아직 Constructor를 만들지 않았기 때문에 객체들은 모두 같은 name,xp를 가질 것이다. 그럼 이제 생성자를 사용하자.
Constructor
- 객체가 생성될 때 호출되는 메서드로, 객체 초기화 작업을 해준다.
- 클래스 이름과 생성자 이름은 같아야 한다.
- 생성자는 중복정의 가능하다
이때 name과 xp를 사용자로부터 받아오기 위해 late를 써서 null safety를 해준다. (필수)
class Player{
late final String name;
late int xp;
Player(String name,int xp){
this.name=name;
this.xp=xp;
}
}
void main(){
var player1=Player('nico',1500);
var player2=Player('lynn',2000);
}
- 이미 필드에 타입을 명시해주었기 때문에 parameter에 다시 전부 명시하는 것이 번거롭다. (딱히?)
다음의 축약형을 정말 많이 쓰니까 기억해두자.
class Player{
//late를 지울수있다
final String name;
int xp;
Player(this.name,this.xp);
}
void main(){
var player1=Player('nico',1500);
var player2=Player('lynn',2000);
}
Named constructor parameters
- 넘겨야 할 parameter가 2개 이상 넘어가면 positional parameter 방식은 왔다갔다 매우 번거롭다.
- positional parameter과는 달리, named parameter은 required를 전부 명시해야 한다.
→ 그래서 name parameter에서 null safety 에러가 자주 발생하는 것!
class Player{
final String name;
int xp;
String team;
int age;
Player({
required this.name,
required this.xp,
required this.team,
required this.age
});
void sayHello() => print("Hi this is $name");
}
void main(){
var player1=Player(name:'nico',xp:1200,team:'red',age:12,);
var player2=Player(name:'lynn',xp:2000,team:'blue',age:15,);
}
Named Constructors
- 클래스 이름과 다른 이름을 갖는 생성자로, 필요에 따라 다른 인자를 받아 클래스를 초기화하는 생성자
- : 뒤에 필드들을 초기화하는 부분을 넣음 (지정된 필드 포함)
class Player{
String name;
int age;
String team;
Player({
required this.name,
required this.team,
required this.age,
});
Player.createBlue({ //team='blue'만 지정
required String name,
required int age
}) : this.name=name,this.age=age,this.team='blue';
Player.createRed({ //team='red'만 지정
required String name,
required int age
}) : this.name=name,this.age=age,this.team='red';
void printInfo()=>print("$name,$team,$age");
}
void main(){
var player1=Player(name:'nico',team:'a',age:20);
player1.printInfo(); //nico,a,20
var player2=Player.createBlue(name:'lynn',age:30);
player2.printInfo(); //lynn,blue,30
var player3=Player.createRed(name:'lynn',age:30);
player3.printInfo(); //lynn,red,30
}
forEach()
- 콜백함수를 배열 요소 각각에 대해 실행
- 콜백함수는 다음 매개변수와 함께 호출된다.
- current value: 처리할 요소 값
- index(선택적): 각 요소의 순서
- array(선택적): 원본 배열 자체 // [1,2,3]
다음은 콜백함수의 모습이다. 콜백함수는 각 요소에 대해 실행되며, 배열 요소를 뜻하는 매개변수를 반드시 하나 이상 사용해야한다.
numbers.forEach(function() {
//code
});
const numbers=[1,2,3];
//기존의 for 반복문 사용
for(i=0;i<numbers.length;i++){
console.log(i,numbers[i]);
}
//forEach 사용
numbers.forEach((number,index)=>{
console.log(index,number);
});
☆ API 활용 예제 (with named constructor)
- 플러터에서 fromJson이라는 named constructor를 자주 쓰게 될 것이다.
- Map<String,dynamic> playerJson을 만들어서 Player 클래스의 property들을 초기화하자.
class Player{
final String name;
String team;
int xp;
Player.fromJson(Map<String, dynamic> playJson)
: name=playJson['name'],
team=playJson['team'],
xp=playJson['xp'];
void sayHello() => print("Hi this is $name");
}
void main(){
var apiData = [
{
'name':'nico',
'team':'blue',
'xp':0,
},
{
'name':'lynn',
'team':'blue',
'xp':10,
},
{
'name':'dal',
'team':'red',
'xp':20,
},
];
apiData.forEach((playerJson){
var player=Player.fromJson(playerJson);
player.sayHello();
});
}
//console 출력부분
Hi this is nico
Hi this is lynn
Hi this is dal
Cascade Notation
Player 객체 nico를 만든 후, 프로퍼티 값을 변경하려고 한다.
<기존 방식>
class Player{
String name;
String team;
int xp;
Player({
required this.name,
required this.team,
required this.xp,
});
void sayInfo() => print("$name,$team,$xp");
}
void main(){
var nico = Player(name:'nico',team:'a',xp:50);
nico.name = 'las';
nico.team = 'b';
nico.xp = 100;
nico.sayInfo();
}
<Cascade Notation>
class Player{
String name;
String team;
int xp;
Player({
required this.name,
required this.team,
required this.xp,
});
void sayInfo() => print("$name,$team,$xp");
}
void main(){
var nico = Player(name:'nico',team:'a',xp:50)
..name = 'las'
..team = 'b'
..xp = 100;
nico.sayInfo();
}
Enum
- 선택의 폭을 좁혀주어 개발자들이 실수를 하지않게끔 도와준다.
- 색깔 설정 시 Color라는 enum이 있기 때문에 color:'red' 대신 color:Color.red 를 사용할 것임
위의 예시에서 team 속성을 enum Team으로 만들어주었다.
enum Team {red,blue}
class Player{
String name;
Team team;
int xp;
Player({
required this.name,
required this.team,
required this.xp,
});
}
void main(){
var nico = Player(name:'nico',team:Team.blue,xp:50)
}
Abstract Classes
- 추상화 클래스로는 객체를 생성할 수 없다.
- 다른 클래스에서 이를 extends(상속,확장)하여 사용할 수 있음
- 이를 상속받는 모든 클래스들이 갖고 있어야하는 메소드를 정의한다.
abstract class Human{
void walk();
}
class Player extends Human{
...
void walk()=>print('walking');
}
class Coach extends Human{
...
void walk()=>print('running');
}
Inheritance(상속)
- Human 클래스를 상속한 Player 클래스는 Human의 프로퍼티들과 메소드를 가져온다.
- 상속받은 Player에서는 부모 클래스의 생성자 함수의 호출이 필요하다.
- 왜? Human의 생성자 함수에서 name 값을 필드에 지정하기 때문이다.
- super 키워드는 확장(상속)한 부모 클래스의 프로퍼티에 접근하거나 메소드를 호출할 수 있게 한다.
- super를 통해 부모 클래스와 상호작용 할 수 있다.
- 자식 생성자에서 super(name) 실행 시, 부모 생성자가 실행되고 보내준 name을 넘겨받는다.
enum Team {blue,red}
class Human{ //부모 클래스
late final String name;
Human(this.name); //부모 생성자
void sayHello()=>print("Hi this is $name");
}
class Player extends Human{ //자식 클래스
final Team team;
Player({ //자식 생성자
required this.team,
required String name, //name만 전달
}) : super(name);
}
void main() {
var player = Player(team:Team.blue, name:'nico');
player.sayHello();
}
//named argument 사용
enum Team {blue,red}
class Human{ //부모 클래스
late final String name;
Human({required this.name}); //부모 생성자
void sayHello()=>print("Hi this is $name");
}
class Player extends Human{ //자식 클래스
final Team team;
Player({ //자식 생성자
required this.team,
required String name, //name만 전달
}) : super(name:name);
}
void main() {
var player = Player(team:Team.blue, name:'nico');
player.sayHello();
}
- @override 기능을 통해 같은 이름의 메소드를 자식클래스에서 새로 만든 메소드로 대체할 수 있다.
enum Team {blue,red}
class Human{ //부모 클래스
late final String name;
Human(this.name);
void sayHello() {
print("Hi this is $name");
}
}
class Player extends Human{ //자식 클래스
final Team team;
Player({
required this.team,
required String name,
}) : super(name);
@override void sayHello() {
super.sayHello();
print('and my team is ${team}');
}
}
void main() {
var player = Player(team:Team.blue, name:'nico');
player.sayHello();
}
Mixin
- 생성자가 없는 클래스 (Mixin의 조건이다.)
- with 키워드를 사용하여 다른 클래스의 프로퍼티와 메소드를 긁어와서 사용할 수 있다.
- Mixin의 핵심은 여러 클래스에 재사용이 가능하다는 점이다.
enum Team {blue,red}
class Strong {
final double strength=150.99;
}
class Quick {
void run()=>print("run!!!");
}
class Player with Strong,Quick {
final Team team;
Player({
required this.team,
});
}
void main(){
var player=Player(team:Team.red);
print(player.strength);
player.run();
}