2024.01.26(금)

👤객체 지향 프로그래밍 방식

  • 왜 객체지향 철학을 이해해야 하는가?
    • 자바스크립트가 객체를 사용하는 객체 기반 언어이다.
    • 객체를 생성하는 원리를 이해하면 객체를 더욱 잘 사용할 수 있다.
    • 타입스크립트와 리액트 기반에서 필요하다.

🆚절차 지향 vs 객체 지향

  • 절차 지향 프로그래밍 = 순차적, 하향식, 폭포수 방식

    프로그램을 기능중심으로 바라보는 방식으로 "무엇을 어떤 절차로 할 것인가?"가 핵심이 된다. 즉, 어떤 기능을 어떤 순서로 처리하는가에 초점을 맞춘다.

    • 기본 단위: 함수
    • 중간에 문제가 발생하면 뒤쪽을 모두 바꿔야 한다.
    • 소형 프로그래밍의 경우 작은 기능을 수반하기 때문에 객체 지향보다는 절차 지향이 적합
      • 작은 기능을 객체별로 나눌 경우, 오히려 복잡해질 수 있기 때문
  • 객체 지향 프로그래밍

    기능이 아닌 객체가 중심이 되며 "누가 어떤 일을 할 것인가?"가 핵심이 된다. 즉, 객체를 도출하고 각각의 역할을 정의해 나가는 것에 초점을 맞춘다.

    • 기본 단위: 객체
    • 유연하다.
    • 대형 프로그래밍의 경우 많은 기능을 수반하기 때문에 절차 지향보다는 객체 지향이 적합
      • 각 객체가 하는 역할이 많아도, 많은 역할을 객체로 묶을 수 있기 때문

🗿객체 지향 철학

  1. 추상화(abstraction)💭

    객체들의 공통적인 특징(기능, 속성)을 도출하는 것

    • 객체지향적 관점에서는 클래스를 정의하는 것을 추상화라고 할 수 있다.
  2. 캡슐화(encapsulation)💊

    객체가 독립적으로 역할을 할 수 있도록 데이터와 기능을 하나로 묶어 관리하는 것

    • 실제로 구현되는 부분을 외부에 드러나지 않도록 하여 정보를 은닉할 수 있다.
    • 데이터를 보이지 않고 외부와 상호작용을 할 때는 메소드를 이용하여 통신을 한다. 보통 라이브러리로 만들어서 업그레이드해 사용할 수 있다.
  3. 상속성(inheritance)👑

    하나의 클래스가 가진 특징(함수, 데이터)을 다른 클래스가 그대로 물려받는 것

    • 이미 작성된 클래스를 받아서 새로운 클래스를 생성하는 것
    • 기존 코드를 재활용해서 사용함으로써 객체지향 방법의 중요한 기능 중 하나에 속한다.
  4. 다형성(polymorphism)🎭

    약간 다른 방법으로 동작하는 함수를 동일한 이름으로 호출하는 것

    • 동일한 명령의 해석을 연결된 객체에 의존하는 것
    • 오버라이딩(Overriding)과 오버로딩(Overloading)
      • 오버라이딩(Overriding)

        부모클래스의 메소드와 같은 이름을 사용하며 매개변수도 같되 내부 소스를 재정의하는 것

        • 덮어쓰기

        • 상속 개념 기반

        • 수직적

          class Dog {
          	public Dog() {
          	    eyes = 0;
          	    nose = 0;
          	    mouse = 0;
          	    ears = 0;
          	}
          	
          	protected int eyes, nose, mouse, ears;
          	
          	**virtual** public void bark() {
          	    Console.WriteLine("Bow-wow!");
          	}
          }
          class Pudle : Dog {
              public Pudle() {
          	    base.eyes = 1;
          	    base.nose = 2;
          	    base.mouse = 3;
          	    base.ears = 4;
              }
              
              public **override** void bark() {    // 부모클래스의 bark 메소드 오버라이딩
                  Console.WriteLine("Woof-woof");
              }
          }
      • 오버로딩(Overloading)

        같은 이름의 함수를 여러 개 정의한 후 매개변수의 타입이나 개수를 다르게 하여 같은 이름을 경우에 따라 호출하여 사용하는 것

        • 쌓기

        • 수평적

          int Plus(int a, int b) {
              return a + b;
          }
          int Plus(int a, int b, int c) {
              return a + b + c;
          }
          double Plus(double a, double b) {
              return a + b;
          }
  5. 동적 바인딩(Dynamic Binding)🔗

    • 가상 함수를 호출하는 코드를 컴파일할 때, 바인딩을 실행시간에 결정하는 것.
    • 파생 클래스의 객체에 대해, 기본 클래스의 포인터로 가상 함수가 호출될 때 일어난다.
    • 함수를 호출하면 동적 바인딩을 통해 파생 클래스에 오버라이딩 된 함수가 실행
    • 프로그래밍의 유연성을 높여주며 파생 클래스에서 재정의한 함수의 호출을 보장(다형 개념 실현)

📂클래스 (C#)

멤버 변수와 멤버 함수(메소드)로 구성 (사용자 정의 데이터 타입)

  • 사물의 특성을 정리하여 상태(필드)행동(메소드)로 표현 → 추상화
  • 추상화된 결과를 하나의 클래스에 포함시키고 외부에서 직접적으로 접근할 수 없도록(메소드를 통해서만 접근할 수 있도록) 보호 → 캡슐화
  • 구조체와 비슷
    class 클래스명 {                        // 클래스 선언
    		접근지정자 클래스명() {}           // 생성자
    		접근지정자 ~클래스명() {}          // 소멸자
    		접근지정자 자료형 멤버변수(필드)     // 변수 선언
    		접근지정자 자료형 메소드() {}      // 메소드
    }
    class Dog {
        public Dog() {}
        public ~Dog() {}
        protected int eyes, nose, mouse, ears;
        public void bark() {}
    }
  • 접근 지정자
    접근 지정자의미
    public누구나 접근 가능
    protected상속 관계에 있을 때 상속 받은 자식 클래스에서만 접근 가능 (외부에서는 private처럼, 자식은 public처럼 사용 가능)
    internal같은 어셈블리(프로젝트) 내의 모든 클래스가 접근 가능
    protected internalprotected와 internal의 의미를 모두 포함
    private내 클래스 내부에서만 접근 가능하고, 외부에서는 절대 접근 불가능
  • 객체의 선언
    Dog a = new Dog();
    • new 연산자가 malloc과 비슷한 역할을 한다고 생각하면 됨
    • 일반 변수와 구분하기 위해 “객체(object)”라고 부름
  • 생성자(constructor)

    객체 생성 시 자동으로 호출되는 초기화 전용 메소드

    • 모든 변수는 선언이 되면 값을 초기화해야 한다.
    • 객체도 본질적으로 변수이므로 선언되면 초기화해야 한다.
  • 소멸자(Destructor)

    객체가 소멸할 때 자동 호출되는 메소드

    • free와 비슷한 역할을 한다고 생각하면 됨
  • 상속
    접근지정자 클래스명 : 부모클래스명
    {
        // 멤버 목록
    }

📜인터페이스

메소드의 목록만을 가지고 있는 명세(Specification) (사용자 정의 데이터 타입)

  • 메소드의 목록만 선언하고 구현은 하지 않음
  • 본체가 정의되지 않는 추상 메소드만을 가짐
  • 인터페이스의 목적은 class처럼 기존의 기능을 추가하거나 수정의 개념보다는 동일한 개념의 기능을 새롭게 구현하는 것
    • 클래스 상속 목적: 기능 확장(extends)
      • 단일 상속만 가능
    • 인터페이스 상속 목적: 기능 명세 (기능의 나열)
      • 자식 클래스에서 상속 (다중 상속 가능)
      • 구현(implements)의 의미가 강함
  • 공동 작업 시 표준을 정하는 역할
  • 인터페이스 선언
    접근지정자 interface 이름 (: 기반인터페이스) {
        // 메소드 목록
    }
  • 인터페이스를 상속 받는 클래스 형태
    접근 지정자 class 자식클래스명 : 인터페이스명 {
        // 메소드 오버라이딩
    }
  • 예시
    using System;
    
    public interface IUnit {    // interface의 경우 이름에 prefix로 I를 붙이는 관습이 있다.
        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();
      }
    }

💾메모리 관리

  • C언어의 경우 개발자가 메모리를 동적으로 할당(malloc)하고 해제(free)해주어야 함
  • 자바스크립트의 경우 가비지 컬렉터(garbage collector)가 메모리를 자동 관리

🗑️가비지 컬렉터

  • 가비지 컬렉터는 백그라운드에서 항상 실행중이며 더 이상 사용되지 않는 메모리, 즉 쓰레기를 찾아 회수
  • 개발자는 new 연산자로 필요한만큼 객체나 메모리를 할당해서 쓰다가 그냥 나가 버리면 됨
    void func() {
             int[] ar = new int[10];
    
             DateTime Now = new DateTime(1970, 6, 29);
    
             // 객체를 실컷 사용한다.
    }

🔄가비지 컬렉터의 힙 관리 동작

  • 객체가 만들어지고 회수하기를 반복하면 힙의 중간 중간이 비는 단편화(fragmentation) 현상 발생
    • 중간의 객체가 해제되면 남은 공간은 많아도 조각난 상태여서 큰 메모리 할당이 불가능
  • 남아 있는 메모리를 이동시켜 큰 덩어리를 만드는 컴팩션(compaction)을 수행
    • 남은 객체를 앞쪽으로 이동시켜 단편화를 제거

💡 힙은 항상 관리중이어서 객체의 번지는 고정되어 있지 않고 힙의 어딘가를 떠 돌아 다닌다.
그래서 포인터를 쓸 수 없지만 대신 객체와 함께 갱신되는 참조자를 통해 액세스할 수 있다.
응용 프로그램 입장에서 컴팩션은 투명하다.
- 참고 자료

🚀람다를 통한 화살표 함수의 이해

  • 익명 메소드
    • 메소드를 미리 정의하지 않고 사용할 때 정의

    • 코드가 간결해짐

    • 별도의 메소드를 만들지 않으므로 코딩 오버헤드를 줄임

    • 내용 자체가 복잡하면 안됨

    • 람다식에서 사용됨

      using System;
      
      class HelloWorld {
          static int Add(int a) {
              return a + 1;
          }
          
          delegate int CalcDele(int x);   // delegate 키워드는 함수 포인터라고 생각하면 됨
          
          static void Main() {
              Console.WriteLine(Add(1));  // 2
              
              CalcDele d = delegate (int x) {
                  return x + 1;
              };
              Console.WriteLine(d(1));    // 2
          }
      }
  • 람다식
    • 기존 익명 메소드를 더욱 간결하게 만드는 문법

    • 코드를 짧고 간결하게 표현하는 것이 목적

    • 델리게이트 본체를 람다식으로 표현

    • 델리게이트와 인수의 개수 및 타입은 일치해야 함

    • 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);   // delegate 키워드는 함수 포인터라고 생각하면 됨
          
          static void Main() {
              Console.WriteLine(Add(1));  // 2
              
              CalcDele d = x => x + 1;    // 람다식 표현 사용
              Console.WriteLine(d(1));    // 2
          }
      }

이번 주까지해서 타입스크립트를 배우기 전 기초 내용을 강사님께서 설명해주셨는데 정말 만족스러웠다. C#은 잘 모르지만 강사님께서 개념이 어떻게 쓰이는지 쉽게 알려주셔서 후에 타입스크립트를 처음 배울 때 도움이 많이 될 것 같다. 그래도 오늘 내 생일 날까지 공부를 하니 조금 눈물이...ㅋㅋㅋ🥲

profile
이것저것 관심 많은 개발자👩‍💻

0개의 댓글