Post

데브코스 TIL - Day 47

24년 1월 26일 강의를 들은 내용을 기록한 글입니다.

클래스

  • 사용자 정의 데이터타입
  • 추상적인 데이터타입
  • 구조체와 비슷
  • 클래스 = 멤버변수 + 멤버 함수

📘클래스 구조

  • 사물의 특성을 정리하여 필드와 메소드로 표현하는 과정 => 추상화
  • 추상된 결과를 하나의 클래스에 포함시키고 스스로 보호하는 것이 캡슐화

■ 예제

1. 사람

  • 상태(필드): 피부색, 키, 나이, 성별, 이름 …
  • 행동(메소드): 생각한다, 공부한다, 걷는다, 말한다, 먹는다 …

2. 노트북

  • 상태(필드): CPU, 메모리 크기, 하드디스크 …
  • 행동(메소드): 부팅한다. 충전한다. CD-ROM을 읽는다 …

📘클래스 선언 형식

1
2
3
4
5
class 클래스이름{
  접근 지정자 클래스 이름(){...}
  접근 지정자 데이터형 멤버변수(필드);
  접근 지정자 데이터형 메소드(){...}
}

■ 예제

1
2
3
4
class Dog {
  private int eyes, nose, mouth , ears;
  public void bark(){}
}

📘접근지정자 종류

  1. public: 누구나 접근 가능
  2. protected: 상속 관계에서 상속 받은 자식 클래스에서 접근 가능, 그 외에는 접근 불가
  3. private: 내 클래스에서만 접근이 가능하고, 외부에서는 절대 접근 불가
  4. internal: 같은 프로젝트 내의 모든 클래스가 접근 가능
  5. protected internal: protected + internal

📘클래스를 통해 객체 선언 및 생성

  • 클래스를 통해 선언한 변수를 객체라고 함
  • new 연산자를 사용하여 객체를 생성함

■ 예제

  • 객체 선언
1
Dog a;
  • 객체 생성
1
Dog a = new Dog();
  • 객체 사용
1
2
3
4
5
6
7
8
9
class Dog {
  private int eyes, nose, mouth , ears;
  public void bark(){
      Console.WriteLine("개 짖는 소리");
  }
};

Dog a = new Dog();
a.bark(); // 개 짖는 소리
  • 전체 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System;

class Dog {
  private int eyes, nose, mouth , ears;
  public void bark(){
      Console.WriteLine("개 짖는 소리");
  }
};

class HelloWorld {
  static void Main() {
    Dog a = new Dog();
    a.bark();
  }
}

📘생성자

모든 변수는 선언이 되면 초기화를 해야 한다. 객체도 변수이므로 선언되면 초기화를 해야 한다
=> 객체 생성시 초기화시켜주는 메소드가 바로 생성자(constructor)

  • 클래스 이름과 동일한 이름의 함수
  • 초기화 전용이기때문에 리턴타입을 작성하지 않아도 됨
1
2
3
4
5
6
7
8
9
class Dog {
  private int eyes, nose, mouth, ears;
  public Dog(){
    eyes = 2;
    nose = 1;
    mouth = 1;
    ears = 2;
  }
};

상속성

이미 완성된 클래스를 다른 클래스에서 상속시킬 수 있음

1
접근지정자 클래스이름 : 부모클래스 {}

■ 예제

개를 상속받아서 눈의 개수 변경

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Dog {
  protected int eyes, nose, mouth, ears;
  public virtualvoid bark(){
    Console.WriteLine("개 짖는 소리");
  }
  public Dog(){
    eyes = 0;
    nose = 1;
    mouth = 1;
    ears = 2;
  }
};

class Pudle : Dog {
  public Pudle(){
      base.eyes = 2;
      Console.WriteLine("푸들 눈: {0}", eyes);
  }
  public override void bark(){
    Console.WriteLine("왈왈");
  }
};

class HelloWorld {
  static void Main() {
    Dog a = new Dog();
    a.bark(); // 개 짖는 소리

    Pudle pd = new Pudle(); // 푸들 눈: 2
    pd.bark(); // 왈왈
  }
}

다형성

  • 함수의 이름이 같더라도 전달인자의 타입이나 개수에 따라 구분됨

📘오버로딩 (overloading)

메서드 중복 정의

한 클래스 안에 같은 이름의 메소드를 여러개 정의하는 것

■ 예제

  • 매개변수의 타입이 다르므로 오버로딩이 됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Animal{
  public void Overload(int rabbit){
      Console.WriteLine("토끼 {0}마리", rabbit);
  }
   public void Overload(int rabbit, int panda){
      Console.WriteLine("토끼 {0}마리 + 판다 {1}마리", rabbit, panda);
  }
   public void Overload(int rabbit,  int panda, int cat){
      Console.WriteLine("토끼 {0}마리 + 판다 {1}마리 + 고양이 {2}마리", rabbit, panda, cat);
  }
  public void Overload(string rabbit){
      Console.WriteLine("토끼 {0}색", rabbit);
  }
};

class HelloWorld {
  static void Main() {
    Animal ani = new Animal();
    ani.Overload(10); // 토끼 10마리
    ani.Overload(10,3); // 토끼 10마리 + 판다 3마리
    ani.Overload(10,3,5); // 토끼 10마리 + 판다 3마리 + 고양이 5마리
    ani.Overload("핑크"); // 토끼 핑크색
  }
}

📘오버라이딩 (Overriding)

상속받은 메서드를 그대로 사용하는 것이 아니라,
재정의해서 사용하는 것

■ 예제

  • Pudle 클래스에서 override 키워드를 사용해서 Dog 클래스에서 상속받은 bark() 내용을 변경
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Dog {
  protected int eyes, nose, mouth, ears;
  public virtual void bark(){
      Console.WriteLine("개 짖는 소리");
  }
  public Dog(){
    eyes = 0;
    nose = 1;
    mouth = 1;
    ears = 2;
  }
};

class Pudle : Dog {
  public Pudle(){
    base.eyes = 2;
    Console.WriteLine("푸들 눈: {0}", eyes);
  }
  public override void bark(){
    Console.WriteLine("왈왈");
  }
};

class HelloWorld {
   static void Main() {
    Dog dog = new Dog();
    dog.bark(); // 개 짖는 소리

    Pudle pd = new Pudle(); // 푸들 눈: 2
    pd.bark(); // 왈왈

    dog = new Pudle();
    dog.bark(); // 왈왈
  }
}

인터페이스

  • 사용자 정의 타입
  • 메소드 목록만을 가지고 있는 명세
  • 메소드 목록만 선언하고, 구현은 하지 않음 (스펙만 작성)
  • 독립적으로 사용할 수 없음

📘인터페이스 형태

1
접근지정자 interface 이름 : 기반인터페이스{}
  • 인터페이스를 상속받는 클래스 형태
1
접근지정자 class 자식클래스이름 : 인터페이스 {}

📘인터페이스를 사용하는 이유

  • 기능을 추가하거나 수정의 개념보다는 동일한 개념의 기능을 새롭게 구현하는 기능
  • 공동작업 시 표준을 정하는 역할

■ 추상 클래스를 상속하는 경우

  • 일반적으로 클래스를 상속하는 이유는 기능 확장이 목적
  • 기존 기능을 재정의하거나, 새로운 기능을 추가
1
2
3
4
5
6
7
8
9
10
11
12
class 스마트폰기본(){
  통화기능
  문자메세지기능
  와이파이기능
}
class 갤럭시 : 스마트폰기본 {
  통화기능
  문자메세지기능
  와이파이기능
  멀티미디어기능
  블루투스기능
}

■ 인터페이스를 상속하는 경우

  • 기존 기능을 어떻게 정의할 것인지 명세
  • 자식클래스에서 상속
1
2
3
4
5
6
7
8
9
10
11
12
13
interface 통화기능{}
interface 문자메세지기능{}
interface 와이파이기능{}
interface 멀티미디어기능{}
interface 블루투스기능{}

class 스마트폰_기본 : 통화기능, 문자메세지기능, 와이파이기능, 멀티미디어기능, 블루투스기능 {
  // 통화 기능 구현
  // 문자메세지 기능 구현
  // 와이파이 기능 구현
  // 멀티미디어 기능 구현
  // 블루투스 기능 구현
}

■ 인터페이스 사용방법

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public interface IUnit {
  void Attack();
  void move();
}

public class Rabbit : IUnit {
  public void Attack(){
    Console.WriteLine("토끼 앞발 공격!");
  }
  public void move(){
    Console.WriteLine("토끼 뛴다!");
  }
}

public class Panda : IUnit {
  public void Attack(){
    Console.WriteLine("판다 앞발 공격!");
  }
  public void move(){
    Console.WriteLine("판다 뛴다!");
  }
}

class HelloWorld {
  static void Main() {
    Rabbit rabbit = new Rabbit();
    rabbit.Attack(); // 토끼 앞발 공격!
    rabbit.Move(); // 토끼 뛴다!

    Panda panda = new Panda();
    panda.Attack(); // 판다 앞발 공격!
    panda.Move(); // 판다 뛴다!
  }
}

■ 인터페이스 메모리 관리

  • 가바지 컬렉터가 메모리를 자동 관리
  • 사용되지 않는 메모리는 삭제됨(회수)
This post is licensed under CC BY 4.0 by the author.