Front End/Flutter

[Dart] 5. 상속, 접근 지정자, Getter Setter

YJ_SW 2022. 5. 20. 14:18
728x90

5. 상속, 접근 지정자, Getter Setter

class Person {
  String? name;
  setName(String name) {
    this.name = name;
  }

  getName() {
    return name;
  }

  showInfo() {
    print('name is $name');
  }
}
class Student **extends** Person {
  int? studentID;

  **@override**
  showInfo() {
    print('name is **${super.getName()}** and id is $studentID');
  }
}

main() {
  Student student = Student();
  student.studentID = 2020;
  student.setName("Kim");
  student.showInfo();
}

Student 클래스는 Person 클래스를 상속받음

Student : 자식 클래스

name, setName(), getName(), showInfo() 모두 상속 받음, 재 선언 하지 않아도 됨

Person : 부모 클래스

함수의 기능을 재정의

@override 어노테이션을 붙이고 재정의하면 된다.

부모 클래스의 메소드인 getName()에 접근하기 위해서 super 라는 키워드 사용 - 생략해도 무관

객체지향 특징

  1. 추상화 : 공통된 데이터와 메서드를 묶어 이름을 부여 ex) Person class
  2. 캡슐화 : 어떤 객체가 어떤 목적을 수행하기 위한 데이터( 멤버변수)와 기능(메서드)을 적절하게 모으는 것

→ 하나의 기능을 수행하는 객체를 만드는 것

  1. 상속
  2. 다형성

접근 지정자

클래스의 멤버 변수 또는 메서드 앞에 선언되고 종류에 따라 해당 멤버들에게 접근할 수 있는 범위가 달라진다.

public

아무런 키워드 없을 때 public

private

접근 범위 : 라이브러리 ( java의 package )

변수나 메서드 앞에 _ 붙여야 함

int _age;
_sleep() {
}

Getter Setter

멤버 변수를 private으로 선언하고 해당 변수에 접근할 수 있는 메소드는 public으로 선언하면 멤버 변수에 직접적으로 접근하는 것을 막을 수 있다.

class Person {
  String _name =''; // private
  String get name => _name;
  set name(String name) => _name = name;
}

main() {
  Person person = Person();
  person.name = 'Kim';
  print(person.name);
}

추상클래스

추상메소드를 가질 수 있는 클래스

추상 메소드 ( abstract method )

메소드 선언은 되어 있지만 바디가 정의되지 않은 형태

// 추상클래스
abstract class Person {
  eat();
}
class Developer implements Person {
  @override
  eat() {
    print('Developer eat a meal');
  }
}

main() {
  Person person = Developer();
  person.eat();
}

추상 클래스 Person의 추상 메서드인 eat()을 오버라이딩 해야한다.

추상 클래스에서 반드시 추상 클래스만 존재하는 것은 아니다.

But, 일반 메서드도 반드시 임플리먼트 하는 클래스에서 반드시! 재정의 되어야 한다. @override 는 생략 가능

여러 개를 임플리먼트 할 수 있다.

List : 배열 , 순서가 있고 중복 허용

Set : 순서가 없고 중복 허용 X

Map : key-value로 구성, 키는 중복되지 않고 값은 중복 가능

List

List<dynamic> list1 = ['yy','jj','zz',2323,444];
  for (int i = 0; i<list1.length;i++){
    print(list1[i]);
  }

List 여러 타입의 데이터를 섞어서 넣고 싶으면

List<dynamic>

List<var>

사용하면 됨

Set

Set<dynamic> testSet = {1,2.5,'test'};
  testSet.add(1);
  testSet.add(1);
  testSet.add(1);
  testSet.add(1);
  testSet.add(3);
  testSet.add(4);
  testSet.add(3);
  testSet.add('test');
  testSet.add('korea');
 
  for(dynamic each in testSet) {
    print(each);
  }
  • 순서가 없기 때문에 각 요소에 인덱스로는 접근 불가
  • for .. in 문을 통해 접근 가능
  • 중복허용 안하기 때문에 같은 값을 여러 번 추가해도 단 하나만 존재한다.
  • { }로 초기값 세팅

Map

key - value 로 이루어짐

Map<int, String> testMap = {
    1:'Red',
    2:'Orange',
    3:'Yellow',
  };
  testMap[4] = 'Green';
  print(testMap);
  print(testMap[1]);
  print(testMap[5]);

결과

{1: Red, 2: Orange, 3: Yellow, 4: Green} Red null

제네릭 타입

변수 타입을 명확히 표현할 수 있다, 반복되는 코드를 줄일 수 있다.

어떤 자료구조를 만들 때, String 도 지원하고 싶고 Integer도 지원하고 싶고, 많은 타입을 지원하길 원할 때

각 타입에 대해 만들지 않고 다 지원할 수 있는 타입 생성

타입 설명
<T> Type
<E> Element
<K> Key
<V> Value
<N> Number

<> : 타입 매개변수 지정

<> 에 타입 매개변수를 선언하는 것을 매개변수화 타입을 정의한다고 한다.

타입 매개변수

  • 클래스 생성 시 생성자에서 사용
  • 함수 호출 시 인자 값을 전달하기 위해 사용
// 제네릭타입
class Person {
  eat() {
    print('Person eats a food');
  }
}

class Student extends Person {
  eat() {
    print('Student eats a hambuger ');
  }
}
class Manager<T extends Person> {
  eat() {
    print("Manager eats a sandwich");
  }
}

class Dog {
  eat() {
    print('Dog eats a dog food');
  }
}
main() {

  var manager1 = Manager<Person>();
  manager1.eat();

  var manager2 = Manager<Student>();
  manager2.eat();

  var manager3 = Manager();
  manager3.eat();
  var manager4 = Manager<Dog>(); // error
}

제네릭 메서드

class Person {
  T getName<T>(T param) {
    return param;
  }
}
main() {
  var person = Person();
  print(person.getName<String>('Kim'));
  // var manager1 = Manager<Person>();
}

<String>

 

 

 

출처 : https://brunch.co.kr/brunchbook/dartforflutter 스터디하며 정리한 글입니다. 감사합니다.

728x90