반응형

이번 스터디는 class에서 사용되는 super, this라는 키워드에 대해 알아보고자 한다.

아래 소스를 통해 super와 this의 범위, 또한 어떻게 사용하는지에 대해 알아보자.

이번 포스팅은 아래소스로만 쓰여지며, 보는 방법은 주석앞 숫자를 순서대로 

따라가면서 보면 되겠다. 

void main() {
  //Dart언어공부-22.class의 super 와 this의 차이.
  //언제 어떻게 사용하는것이 좋을지 알아보자.

  //7. 엔지니어 클래스를 인스턴스화 하여 값을 호출해보자.
  Engineer eng = new Engineer(
      language: ['dart', 'java', 'javascript'], name: '개발자', building: '공유오피스');

  print(eng.name);
  print(eng.building);
  print(eng.language);

  //9. Engineer클래스의 함수를 호출해보자.
  eng.sayInfo();
  eng.sayName();
}

//1. 직원클래스 생성
class Employee {
  //2. 필수로 입력 받을수 있도록 final키워드를 사용한다.
  final String building;
  final String name;

  //3. 생성자를 만든다.
  Employee(
    String building,
    String name,
  )   : this.building = building,
        this.name = name;
}

//4. 엔지니어 클래스 생성
class Engineer extends Employee {
  //5. 엔지니어가 사용하는 언어에 대해 List로 받기 위해서 선언
  List<String> language;

  //12. 자식클래스와 부모클래스와의 위치 확인을 위한 변수선언
  String name;

  //6. 상속받는 클래스이기 때문에, super키워드를 사용하여 부모클래스에 대한 파라미터도 할당한다.
  Engineer({List<String> language, String name, String building})
      : this.language = language,
        super(
          building = building,
          name = name,
        );

  //8. 기능하나를 선언해 보자.
  void sayInfo() {
    //10. 호출해보면 정상적으로 모든값들이 누락없이 표현된다.
    //여기서의 super는 부모클래스를 뜻하고, this는 자식클래스를 뜻하는데
    //실제 자식클래스에는 없는 building가 나오는 이유는, 부모클래스의 모든것을
    //상속받기 때문에 this에도 포함이 되어있기 때문이다.
    print('저의 이름은 ${super.name}이고, 제가 근무하는 건물은 ${this.building}입니다.');
    print('제가 사용할줄 아는 언어는 ${this.language.join(',')}입니다.');
  }

  //11. 만약 자식클래스에도 name변수가 있다고 가정해보자.
  //13. 선언시작
  void sayName() {
    print('이것은 this의 이름인 ${this.name}이고, 이것은 super의name인  ${super.name}입니다.');
  }
  //14. 당연히 this인 자식클래스에 재정의를 해버리고 생성자에서 할당해주지도 않았기 때문에
  //null값이 발생한다.
  //15. 만약 해당클래스에서 name변수를 다시 지워버리고 13번을 호출하면 super의 값을 그대로 상속받기
  //때문에 super의 name이 그대로 호출된다.
}

 

기본적으로 상속에 대한 개념을 잡고 있다면, 쉽게 이해가 가능하다.

상속을 받았다면, 부모가 가지고 있는 모든것들을 내가 가진채로 사용할 수 있으며,

새롭게 선언하여 사용하면 this라는 키워드를 사용하여 표현이 가능하다.

※상속받았다는 기준하에, super는 부모클래스를 뜻하고

this는 자기자신(자식클래스)을 지칭한다. 앞에 super를 지정하지 않으면 기본적으로 부모로 부터 상속

받은 값을 따라가지만, 자식클래스에 재정의 되어있다면 자식클래스의 값을 가지고 사용한다. (this영향)

super와 this의 범위 차이 스터디 끝.

반응형
반응형

이번 스터디에서는 static 키워드에 대해 알아보려 한다.

간단하게 Static키워드에 대해 말하자면,

인스턴스에 귀속되지 않고, 클래스 통째로 귀속이 되는것. 함수 또는 변수가 통째로 클래스에 귀속이 되는것을 말한다.

빠른 이해를 위해 소스 코드 확인 및 실행해보자.

간단한 직원이라는 클래스를 생성해보자.

조건은 아래와 같다.

1. 근무하고 있는 직원의 이름은 사람마다 다르다.

2. 직원들이 근무하는 건물은 동일하다.(한 건물)

class Employee{
  static String building;
  String name;
  
  Employee(
    String name,
  ):this.name = name;
  
  void printNameAndBuilding(){
    //static을 사용하였기 때문에, building에서는 this를 사용하지 않는다.(사용자체 불가)
    print('제 이름은 ${this.name}이고, ${building} 건물에서 근무 중 입니다.');
  }
  
}

building 변수에만 static을 사용한것을 볼수있다.

또한 printNameAndBuilding에 name앞에는 this를 붙였으나, building에는 붙이지 않은것을 볼수있다.

이는 하나의 인스턴스별로가 아닌, 클래스 자체에 귀속되기 때문이다.

바로 main함수에서 실행을 통해 자세히 알아보자.

void main() {
	Employee chulsoo = new Employee('철수');
    Employee youngHee = Employee('영희');
    
    chulsoo.printNameAndBuilding();
    youngHee.printNameAndBuilding();
}
제 이름은 철수이고, null 건물에서 근무 중 입니다.
제 이름은 영희이고, null 건물에서 근무 중 입니다.

최초 호출시엔 당연히 building값을 할당해 주지않았기 때문에 null값이 나온다.

이제 건물정보를 넣어줘야 하는데, 이때 인스턴스별로 지정해주는것이 아닌, 클래스자체에 직접접근하여 변경한다.

void main(){
	Employee.building = '여의도 공유오피스';
    chulsoo.printNameAndBuilding();
    youngHee.printNameAndBuilding();
}
제 이름은 철수이고, 여의도 공유오피스 건물에서 근무 중 입니다.
제 이름은 영희이고, 여의도 공유오피스 건물에서 근무 중 입니다.

건물정보의 변수값이 변경된 것을 확인할 수 있다.

Static keyword기 때문에, 위와 같이 클래스에 직접 접근하여 사용한다.

Static변수가 아닌 name은 기존처럼 "chulsoo.name="이런식으로 인스턴스별로 바꿔줘야 하지만

Static은 위와 다르게, 인스턴스 자체에 귀속되지 않고 클래스통째로 귀속되기 때문에

해당 클래스로 생성된 인스턴스의 모든 값이 변경된다.

 


void main(){
	Employee.building = '강남 공유오피스';
    chulsoo.printNameAndBuilding();
    youngHee.printNameAndBuilding();  
}
제 이름은 철수이고, 강남 공유오피스 건물에서 근무 중 입니다.
제 이름은 영희이고, 강남 공유오피스 건물에서 근무 중 입니다.

위와 같이 해도 마찬가지로 변경이된다.

아무리 많은 인스턴스를 생성한다 하더라도, static으로 선언된 변수는 클래스에 

직접 접근하여 한번만 변경해도 모든게 바뀐다.


만약 static을 사용하지 않았더라면 각각 인스턴스 별로 변경해줘야 했을것이다. (아래처럼)

"chulsoo.building = '영등포';"

"youngHee.building = '일산';"

......

이렇게 고정되는 값을 하나로 두면, for문같은 반복문을 가지고 인스턴스별로 설정해주는등의 일을 줄일수 있다.

따라서 이런경우엔 클래스 자체에 귀속시키는 static을 사용하는것이 좋다.

 

예제로 보니 이해하기 조금 더 빠른듯 싶다.

Static 스터디 끝.

반응형
반응형

이번 스터디에서는 메소드 오버라이딩에 대해 다뤄보려 한다.

다른말로 하면 "함수덮어쓰기" 정도로 표현할 수 있겠다.

바로 소스와 함께 알아보자.

class Parent {
  final int number;

  Parent(int number) : this.number = number;

  //Function 함수
  //Method
  int calculate() {
    return this.number * number;
  }
}

int형 상수 number값을 가지고, calculate 라는 기능을 가진 함수를 가진 클래스 하나를 선언한다.

※ 클래스 안에 선언된 것들을 보통 메소드라고 부르고, 클래스에 종속되지 않고,

밖에 별도로 선언된 것들을 함수라고 하는데 사실 이것도 분명히 나뉘는것은 아니다.

"메소드 = 함수" 동의어로 생각하면 되겠다.


다음은 위 Parent클래스를 상속받는 자식클래스 하나를 선언하자.

class Child extends Parent {
  Child(
    int number,
  ) : super(number = number);
  
  
  @override
  int calculate(){
    //부모클래스의 calculate함수를 자식클래스에서 덮어쓰기
    return this.number + this.number;

  }
}

여기서 알고 넘어가야 할것들

1. 해당 Child클래스는 Parent클래스를 상속받는다. 

2. @override는 decorator라 불리우며, 부모클래스의 함수를 재정의할때 표시한다.

3. 재정의하게 되면, 자식클래스의 calculate함수를 호출할때, 부모클래스의 함수가 아닌, 재정의된 함수를 호출한다.

4. 데코레이터를 생략해도 동작은한다. 하지만, 타인이 봤을때나 헷갈리지 않도록 표시하는것이 좋다.


본격적으로 main 함수에서 실행해보자.

void main(){
	Parent parent = new Parent(3);
    Child child = new Child(3);
    print(parent.calculate());
    print(child.calculate());
}
9
6

첫번째 print는 부모클래스의 calculate함수를 호출하기 때문에 9가 나온것이고, 

두번째 print는 자식클래스의 재정의된 calculate함수를 호출하기 때문에 6이 나온것이다.

만약, 자식클래스에서 재정의 하지 않았다면 부모클래스의 calculate를 호출하기 때문에 같은값이 9가 나왔을것이다.


이번에는 자식클래스에서 부모클래스의 함수를 직접 호출한 뒤 연산하는 기능을 넣어보자.

먼저 자식클래스의 calculate함수안에 아래와 같이 소스를 변경한다.

class Child extends Parent {
  Child(
    int number,
  ) : super(number = number);
  
  
  //decorator라 한다. 
  @override
  int calculate(){
    int result = super.calculate();

    return result + result;
  }
}

부모클래스의 calculate를 호출하기 위해선, super라는 키워드를 사용하여 호출할 수 있다는 점을 알수있다.

위 결과값은 result변수에 부모클래스의 calculate값을 호출하여 얻은 9에 한번더 9를 더해서 18이 나온다.

※상속을 받는 자식클래스에서는 부모클래스를 재정의하여 사용할 수 있고,

재정의 한다고 하여 부모클래스의 함수는 영향받지 않는다.

 

각자의 역할이 다른 클래스는 주축이 되는 클래스로 부터 상속을 받아 주요기능과 값을 사용하며,

기능에 따라 주요기능에 어떠한 값이나 기능을 더해서 사용해야 하는 경우들이 있다.

그럴때 주로 오버라이딩을 사용하면 좋을듯 싶다.

다시말해서, 현재온도를 계산해주는 클래스가 있다고 하자.

첫번째 자식클래스에서는 부모클래스로 부터 얻은 현재 온도에 한글 문장을 붙여서 안내해주는 기능이 있고,

두번째 자식클래스에서는 부모클래스로 부터 얻은 현재 온도에 영어 문장을 붙여서 안내해주는 기능이 있다고 하자.

 

그럼 자식클래스들에서는 부모클래스로 부터 온도만 받고, 해당 온도를 계산하는 함수를 재정의 한다음

문장을 붙여서 사용할 수도 있는것이다.

적절한 예가 되었을지 모르겠다....

 

오버라이딩 스터디 끝.

반응형
반응형

오늘 스터디한 부분은 '상속' 이라는 개념으로, 지난 스터디에 이어서 class스터디이다.

소스로 들어가기전에 '상속'이라는 단어를 먼저 알고가야 한다.


※상속이란 

1. 뒤를 이음.

2. 일정한 친족 관계가 있는 사람 사이에서, 한 사람이 사망한 후에 다른 사람에게 재산에 관한 권리와 의무의 일체를 이어 주거나, 다른 사람이 사망한 사람으로부터 그 권리와 의무의 일체를 이어받는 일.


위와 같이 정의되고 있다. 하지만 프로그래밍 언어에서의 상속이 위 사전적 내용과 백퍼센트 일치하진 않지만

어느정도의 내용을 가지고 가기 때문에, 반드시 기억하고 스터디를 시작할 필요는 있다.

먼저 상속이란것에 대해 알아보기 위해, class하나를 선언해보자.

void main(){

}

class Color {
  String name;
  String group;
  
  Color({
    String name,
    String group,
  }):this.name=name,
     this.group = group;
  
  void sayName(){
    print("이 색은 ${this.name}입니다.");
  }
  
  void sayGroup(){
    print("그룹은 ${this.group}입니다");
  }
  
}

생성자와 함수를 가지는 간단한 class하나를 준비한다.

다음으로, 상속을 알아보기 위해, class하나를 더 준비한다.

class Fruit extends Color{
   //1. Color클래스의 모든것을 상속받을수 있다.
  Fruit(
    String name,
    String group
  ):super ( // <- 2. 여기서 super는 부모 class를 지칭한다.
    name : name,
    group : group
  ); 
  //<- 3. 이 class가 생성될때, 받는 파라미터를 
  //부모color클래스에 name과group에 넣어준다는것.
  
  void sayCategory(){
    print("여름과일입니다");
  }
}

새로 만든 Fruit 클래스에서는 extends라는 용어를 사용하여 Color클래스를 상속받고 있다. (1번)

여기서 extends의 좌측에는 자식클래스명, 우측에는 부모클래스명을 작성하여 상속받는 클래스 형태를 만든다.

2번을 보면 기존에 this.name = name 형태로 작성되었지만, 지금은 super라고 지정하는 형태를 볼수있다.

여기서 super는 상속받은 부모클래스를 지칭하는 것이며, 해석하자면 Fruit클래스의 생성자에서 

생성당시 받는 파라미터를 부모클래스인 Color의 name과 group에 할당한다. 라는 의미이다.

main 함수에서 실행하여 알아보자.

void main(){
	//color클래스 선언
	Color color = new Color(name:'red',group:'A');
    
    //color클래스 정상동작 확인
    color.sayName();
    color.sayGroup();
    
    //자식클래스로 사용될 fruit클래스를 summer와 melon 파라미터를 넣어서 생성
    Fruit fr = new Fruit('SUMMER','MELON');
    
    //아래 결과를 실행
    print(fr.name);
    print(fr.group);
    
    
}
SUMMER
MELON

Fruit클래스가 생성될때, 받은 SUMMER와 MELON은 생성자를 통해 Color클래스의 name과 group으로 지정되면서

위와 같은 결과값이 나올수 있게되는것이다.

부모클래스로부터 상속을 받을때는 반드시 super키워드를 이용하여 부모클래스의 정보를 입력해주어야 하고

입력해주지 않으면 null값이 표현된다.

 

또한 Fruit클래스는 Color클래스를 상속받았기때문에 Color클래스에 있는 함수를 불러와서 사용할수 있다.

Fruit fr = new Fruit('SUMMER','MELON');
fr.sayName(); //color클래스에 있는 sayName()함수
이 색은 SUMMER입니다.

이렇듯 부모클래스를 상속받아서 정의된 자식클래스는 반드시 생성자를 통해 부모클래스의 정보를 할당하고,

부모클래스의 함수를 그대로 받아서 사용할수 있다는것을 확인하였다.

여기서 중요한 참고사항으로, 자식은 부모클래스를 상속받으면 부모클래스가 가지고 있는 함수와 변수를 

사용할 수 있지만, 반대로 부모클래스는 자식클래스의 변수나 함수를 사용할 수 없다. (중요)

또한, 하나의 부모클래스는 여러개의 자식클래스를 가질수 있으나, 자식클래스는 하나의 부모클래스만 가질수 있다.

 

과연 어디서 이 기능을 사용하는가...? 있어서 좋은점은...? 이런 의문은 곧 다룰 여러예제들을 통해 파악하겠다.

상속 스터디 끝.

반응형

+ Recent posts