[10주차 Day5] 프론트엔드 기초 - 객체지향에 대한 이해

반 히·2024년 5월 3일

데브코스

목록 보기
23/58
post-thumbnail

💡 객체지향 절학의 이해


📌 클래스란

  • 사전적인 의미로는 '학급'이라는 뜻을 가지고 있다.
  • 클래스는 사용자 정의 데이터타입이다.

    클래스 (Class) : 학급

  • 데이터와 메소드를 사용자인 내가 새로 정의한 데이터타입이기 때문에 클래스를 추상적인 데이터타입이라고 함.
  • 클래스의 본질은 데이터타입(Data Type)이라는 점이다.
  • 구조체와 비슷하다.
  • 멤버 변수와 멤버 함수로 구성된다.

📌 클래스의 구성

  • 사물의 특성을 정리하여 필드와 메소드를 표현하는 과정이 추상화
  • 추상화된 결과를 하나의 클래스에 포함시키고 스스로 보호하는 것을 캡슐화.
사물상태(필드)행동(메소드)
사람피부색, 키, 나이, 성별, 이름생각한다. 공부한다. 말한다. 걷는다.
배기량, 차종, 연료의 종류달린다. 멈춘다. 짐을 싣는다.
노트북CPU, 메모리 크기, 하드디스크 용량부팅한다. 충전한다. CD-ROM 읽는다.

📌 클래스의 선언 형식

  • 클래스 선언 시 class 키워드를 쓰고, 그 뒤에 클래스 이름을 붙인다.
  • 클래스의 요소로는 생성자, 멤버 변수, 메소드 등으로 구성한다.
class 클래스 이름	// 클래스 선언
{
	접근 지정자 클래스 이름() { ... }		// 생성자
    접근 지정자 ~클래스 이름() { ... }	// 소멸자
    접근 지정자 데이터형 멤버 변수(필드);	// 변수 선언
    접근 지정자 데이터형 메소드() { ... };	// 메소드 선언
}
  • 직접 개 클래스를 생성해본다.
    객체 지향 언어를 사용하기 위해 GDB의 언어를 C에서 C#으로 바꿔주기
class Dog
{
	public Dog() {}
    private int eyes, nose, mouse, ears;
    public void bark() {}
}

🔗 접근 지정자

접근 지정자의미
public누구나 접근 가능하다.
protected상속 관계에 있을 때 상속 받은 자식 클래스에서 접근 가능하다. 그 외에는 접근 불가하다.
internal같은 어셈블리(프로젝트) 내의 모든 클래스가 접근 가능하다.
protected internalprotected와 internal의 의미를 모두 포함한다.
private내 클래스 내부에서만 접근 가능하고, 외부에서는 절대 접근할 수 없다.

📌 객체의 선언

  • 클래스의 본질은 데이터 타입이다.
  • 데이터타입을 통해 변수를 선언할 수 있다. 변수 선언한다.

    Dog a;

  • 클래스를 통해 선언한 변수를 객체라고 한다.

📌 객체의 생성

Dog a= new Dog();

a는 주소값을 갖고있는 포인터 변수..로 생각하면 됨

using System;

class Dog {
    private int eyes, nose, mouse, ears;
    public void bark() {
        Console.WriteLine("멍멍");
    }
}
class HelloWorld {
  static void Main() {
    Dog a = new Dog();
    a.bark();
  }
}

📌 생성자의 개념

  • 모든 변수는 선언이 되면 값을 초기화해야 한다.
  • 객체도 본질적으로 변수이므로 선언되면 초기화해야 한다.
  • 객체 생성 시 초기화 전용 메소드를 제공하는데 바로 '생성자(constructor)'이다.
    • 즉, 초기화 함수임.
  • 객체 생성 시 자동으로 호출되는 메소드.
  • 생성자는 클래스의 이름과 동일함.
    • 외부에서 접근 가능해야 하므로 public 타입이어야 함.
    • 리턴 타입 필요 없음
    • new 연산을 통해서 객체가 생성되는 순간에 생성자도 호출됨.
using System;

class Dog {
    private int eyes, nose, mouse, ears;
    public void bark() {
        Console.WriteLine("멍멍");
    }
    public Dog() {
        eyes = 0;
        nose = 0;
        mouse = 0;
        ears = 0;
    }
}
class HelloWorld {
  static void Main() {
    Dog a = new Dog();
    a.bark();
  }
}

📌 상속성

  • 현실 세계의 상속 개념
    • 부모님이 나에게 집을 상속하였다.
    • 부모님이 나에게 100만원을 상속하였다.
  • 클래스의 상속
    • 부모 클래스 : 상속을 해주는 클래스
    • 자식 클래스 : 상속을 받는 클래스
  • 이미 완성된 클래스를 다른 클래스에 상속할 수 있음.
  • 부모 클래스로부터 상속을 받을 때 클래스 이름 끝에 콜론(:), 자바의 경우 extends를 붙인 후 부모클래스의 이름을 적는다.
접근 지정자 클래스 이름 : 부모 클래스
{
	// 멤버 목록
}
using System;

class Dog {
    protected int eyes, nose, mouse, ears;
    public void bark() {
        Console.WriteLine("멍멍");
    }
    public Dog() {
        eyes = 0;
        nose = 0;
        mouse = 0;
        ears = 0;
    }
}
class Retriever : Dog {
    public Retriever() {
        base.eyes = 2;
        Console.WriteLine("리트리버 눈 : {0}", eyes);
    }
}
class HelloWorld {
  static void Main() {
    Dog a = new Dog();
    a.bark();
    Retriever rt = new Retriever();
  }
}

protected : 외부에서는 private처럼 보임. 그러나 상속 관계에서 자기 자식에게는 public처럼 접근할 수 있게 허용해줌
base : 부모 객체를 나타냄.


📌 다형성

  • 다양한 형태의 속성을 갖는다는 의미
  • 함수의 이름이 같더라도 전달인자의 타입이나 개수에 따라 구분된다.
  • 객체지향에서는 대표적으로 오버로딩(overloading)오버라이딩(overriding) 기법이 있다.

🔗 오버로딩 (overloading)

  • 사전적 의미는 '과적하다', '적재하다'라는 의미를 가지고 있다.
  • 겉모습은 똑같지만 내용이 다른 경우
  • 이름이 같은 함수일지라도 전달인자 타입이나 개수가 다른 경우
  • 같은 이름의 함수에 같은 개수의 전달인자가 서로 다른 타입으로 존재하는 경우
int Plus(int a, int b) {
	return a + b;
}
char Plus(char a, char b) {
	return a + b;
}
double Plus(double a, double b) {
	return a + b;
}
using System;

public class Zerg {
    public void Overload(int zerggling) {
        Console.WriteLine("저글링 {0}마리", zerggling);
    }
    public void Overload(int zerggling, int hydra) {
        Console.WriteLine("저글링 {0}마리 + 히드라 {1}마리", zerggling, hydra);
    }
    public void Overload(int zerggling, int hydra, int lurker) {
        Console.WriteLine("저글링 {0}마리 + 히드라 {1}마리 + 럴커 {2}마리", zerggling, hydra, lurker);
    }
    public void Overload(char zerggling) {
        Console.WriteLine("저글링 {0}등급", zerggling);
    }
}
class HelloWorld {
  static void Main() {
    Zerg zerg = new Zerg();
    zerg.Overload(10);
    zerg.Overload(10, 20);
    zerg.Overload(10, 20, 30);
    zerg.Overload('A');
  }
}

🔗 오버라이딩 (overriding)

  • 오버라이딩은 '위로 올라탄다', '엎어친다'는 의미를 갖는다.
    • 재정의
  • 무언가에 올라타서 기존의 것을 덮어버린다는 개념
  • 상속의 개념이 기반이 되어야 한다.
  • 함수 포인터를 객체 포인터의 형태로 확장한 형태
using System;

class Dog {
    protected int eyes, nose, mouse, ears;
    virtual public void bark() {
        Console.WriteLine("멍멍");
    }
    public Dog() {
        eyes = 0;
        nose = 0;
        mouse = 0;
        ears = 0;
    }
}
class Retriever : Dog {
    public Retriever() {
        base.eyes = 2;
        Console.WriteLine("리트리버 눈 : {0}", eyes);
    }
    public override void bark() {
        Console.WriteLine("월월");
    }
}

class Chihuahua : Dog {
    public Chihuahua() {
        base.eyes = 2;
        Console.WriteLine("치와와 눈 : {0}", eyes);
    }
    public override void bark() {
        Console.WriteLine("캉캉");
    }
}
class HelloWorld {
  static void Main() {
    Dog dog = new Dog();
    dog.bark();
    Retriever rt = new Retriever();
    rt.bark();
    
    dog = new Chihuahua();
    dog.bark();
  }
}


💡 인터페이스에 관하여


📌 인터페이스란

  • 인터페이스란 메소드의 목록만을 가지고 있는 명세(Specification), 사용자 정의 타입이다.
  • 메소드의 목록만 선언하고 구현은 하지 않는다.
    • 내부의 메소드는 구현하지 않음
    • 인터페이스를 상속받는 자식 클래스에서는 반드시 그 메소드를 오버라이딩해서 구현해야 함.
  • 인터페이스의 선언 형태
접근지정자 interface 이름 : 기반 인터페이스
{
}
  • 인터페이스를 상속받는 클래스의 형태
접근지정자 class 자식클래스이름 : 인터페이스
{
}

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

  • 인터페이스는 본체가 정의되지 않는 추상메소드만 갖는다.
  • 인터페이스의 목적은 기존의 기능을 추가하거나 수정의 개념보다는 동일한 개념의 기능을 새롭게 구현하는 기능이다.
  • 공동작업 시 표준을 정하는 역할

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

  • 추상 클래스 : 구체적이지 않은 클래스
  • 일반적으로 클래스를 상속하는 이유는 기능의 확장이 목적이다.

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

  • 인터페이스에서 기능을 명세하고, 자식클래스에서 상속한다.
    • 예 ) 스마트폰
    • 스마트폰의 기능 목록 : 통화기능, 문자메시지, 와이파이, 블루투스, 멀티미디어 등등..
    • 스마트폰과 상속 관계의 개념이 아니라 여러가지 기능의 나열
  • 클래스는 다중 상속이 되지 않지만, 인터페이스는 다중 상속이 됨.
interface 통화기능 {}
interface 문자메시지기능 {}
interface 와이파이기능 {}
interface 멀티미디어기능 {}
interface 블루투스기능 {}
class 스마트폰_기능 통화기능, 문자메시지기능, 와이파이기능, 멀티미디어기능, 블루투스기능
{
	통화기능구현
    문자메시지구현
    와이파이구현
    멀티미디어구현
    블루투스구현
}
  • interface에서는 implements를 사용함

📌 인터페이스 코드 작성

  • 인터페이스를 생성하고, 인터페이스로부터 상속받은 클래스를 구현
using System;
public interface IUnit {
    void Attack();
    void Move();
}

public class Zergling : IUnit {
    public void Attack() {
        Console.WriteLine("저글링 : 공격한다.");
    }
    public void Move() {
        Console.WriteLine("저글링 : 이동한다.");
    }
}

public class Dragoon : IUnit {
    public void Attack() {
        Console.WriteLine("드라군 : 공격한다.");
    }
    public void Move() {
        Console.WriteLine("드라군 : 이동한다.");
    }
}
class HelloWorld {
  static void Main() {
    Zergling zerg = new Zergling();
    zerg.Attack();
    zerg.Move();
    
    Dragoon dragoon = new Dragoon();
    dragoon.Attack();
    dragoon.Move();
  }
}

📌 메모리 관리

  • 플랫폼 기반의 객체 지향 언어는 가비지 컬렉터가 메모리를 자동 관리한다.
  • 백그라운드에서 더 이상 사용되지 않는 메모리를 찾아 회수한다.
void func() {
	int[] ar = new int[10];
    DateTime Now = new DateTime(2002, 6, 25);
    // 객체를 실컷 사용한다
}
  • 객체가 만들어지고 가비지 컬렉터에 의해 회수가 되는 것이 계속 반복됨.
    • 이런 것들이 계속 반복되면, 힙 메모리에서 데이터 사이 중간에 빈공간이 발생함 (이를 단편화 현상이라고 함)
    • 가비지 컬렉터는 이렇게 중간에 빈 공간이 발생하면 남아있는 메모리들을 이동시켜 큰 덩어리로 만들어줌 (이를 컴팩션이라고 함)
    • 빈 공간을 없애주고 사용할 수 있는 메모리를 만들어줌

## 💡 람다를 통한 화살표 함수의 이해 --- ### 📌 익명 메소드 - 자바스크립트의 익명 메소드와 화살표 함수의 원조는 람다식임. - 콜백 함수는 이벤트 기반으로, 이벤트 발생 시에 미리 등록된 함수를 호출하는 구조임. - 특정 이벤트에서만 사용할 함수이므로 굳이 이름 없이 사용할 수 있는 것 - 따라서 익명 메소드가 존재함. - 메소드를 미리 정의하지 않고 사용할 때 정의한다. - 익명 메소드를 사용하면 코드가 간결해진다. - 익명 메소드는 별도의 메소드를 만들지 않으므로 코딩 오버헤드를 줄일 수 있다. - 익명 메소드는 내용 자체가 복잡하면 안 된다. - 익명 메소드는 람다식에서 사용된다.

📌 람다식이란

  • 기존 익명 메소드를 더욱 간결하게 만든다
  • 코드를 짧고 간결하게 표현하는 것이 목적이다.
  • 일반 메소드 기반
using System;
class HelloWorld {
    static int Add(int a) {
        return a + 1;
    }
    static void Main() {
        Console.WriteLine(Add(3));
    }
}
  • 익명 메소드 기반
using System;

class HelloWorld {
    static int Add(int a) {
        return a + 1;
    }
    
    delegate int CalcDele(int x);
    
    static void Main() {
        Console.WriteLine(Add(3));
        CalcDele d = delegate (int x) {
            return x + 1;
        };
        Console.WriteLine(d(3));
    }
}

📌 람다식 표현

  • delegate 본체를 람다식으로 표현한다.
  • 델리게이트와 인수의 개수 및 타입은 일치해야 한다.

    (인수) => 표현식 또는 명령문

  • (x, y) => x + y람다식은 "x와 y가 x+y가 된다."로 읽는다.
  • Delegate 키워드는 사라지며 람다식을 의미하는 => 기호로 대체된다.
delegate(int x, int y) { return x + y; }

     ↓

(x, y) => x + y;

즉, 위의 코드를 아래와 같이 바꿀 수 있음

using System;

class HelloWorld {
    static int Add(int a) {
        return a + 1;
    }
    
    delegate int CalcDele(int x);
    
    static void Main() {
        Console.WriteLine(Add(3));
        CalcDele d = x => x + 1;
        Console.WriteLine(d(3));
    }
}

0개의 댓글