OOP - 1

귀찮Lee·2022년 5월 10일
0

Java

목록 보기
3/15

◎ 객체지향 프로그래밍 (OOP, Object Oriented Programming)

  • 절차적 프로그래밍(Procedure Programming)
    • 명시된 순서대로 처리한 다음 결과를 도출하는 방식
    • 문제점: 조금만 복잡해져도 순서도로 나타내는게 불가능할 정도로 유지,보수가 힘듦
  • 객체지향 프로그래밍(OOP, Object Oriented Programming)

    • 특정 객체 안에 그 객체의 속성(field) 와 기능(Method)를 넣어 객체들의 상호작용으로 특정 기능을 구성한다.
    • 유지 보수가 매우 용이, 확장성이 좋음
    • OOP는 프로그래밍 방법론의 하나일 뿐, Java가 무조건 OOP를 의미하지는 않는다.
  • 객체지향 프로그래밍의 장단점

    • 장점 : 유지 보수가 매우 용이, 확장성이 좋음, 생산성 향상, 자연적인 모델링
    • 단점 : 개발 속도가 느림, 실행 속도가 느림, 코딩 난이도 상승
    • 참고 : https://radait.tistory.com/4

◎ 클래스(Class)와 객체(Object)

  • 용어 정리

    • 클래스(Class) : 객체를 정의한 설계도, 틀 (객체를 생성하는데 사용)
    • 인스턴스 (Instance) : 클래스를 통해 만들어내 메모리에 할당한 데이터
    • 인스턴스화 : 클래스로부터 Object를 만드는 과정 (Object를 메모리에 올리는 과정)
    • 객체 (Object) : 클래스를 통해 만들어진 실제로 사용할 수 있는 실체 (인스턴스를 포괄하는 넓은 의미)
  • Class 구성요소

    • 필드(field) : 클래스의 속성을 나타냄
    • 메서드(Method) : 클래스의 기능(코드 모음)을 나타냄
    • 생성자 : 클래스의 객체를 생성하는 역할을 함
    • 이너 클래스(Inner Class) : 클래스 내부의 클래스를 나타냄
      • 필드, 매서드, 이너 클래스를 모두 객체의 멤버(member) 라고함
    public class ClassExample {
        float x = 10.0f; // 필드 (field)
        void methodExample() {...} // 메서드 (Method)
        ClassExample() {...} // 생성자
        class ExampleClass2 {...} // 이너 클래스 (Inner Class)
    } 
  • 객체의 생성방법

    public class Main {
        public static void main(String[] args) {
    
        // 모두 같은 Class를 통해 만들어졌지만 다른 Instance이다.
        // (안에 가지고 있는 member들의 값들은 모두 다를 수 있다.)
        Car redCar = new Car();
    
        Car buleCar = new Car(); // 선언과 초기화를 동시에 함
    
        Car greenCar; // 선언
        greenCar = new Car(); // 할당(초기화)
    }
  • 객체의 생성과 메모리 저장 - 추가 내용

    Car redCar = new Car();
    // Car : 클래스
    // redCar : 참조 변수
    • 스택 (메모리) 영역 (Stack Area) :

      • 참조 변수 " redCar " 를 저장 (해당 객체의 힙에 저장되어 있는 주소값을 스택 영역에 저장)
      • 지역변수 저장
    • 클래스 영역 (Class Area) :

      • 클래스 " Person " 을 저장
      • 객체 멤버중에 메서드를 클래스 영역 내부 "인스턴스 메서드 영역" 에 저장하여 메서드를 공유하여 사용
    • 힙 메모리 영역 (Heap Area) :

      • 생성자로 만들어진 객체는 힙 메모리 영역에 저장
      • 객체 내부에는 클래스의 멤버들이 위치함 (필드, 이너 클래스)
      • 멤버 중에 메서드는 클래스 영역 내부에 저장
    • 객체 생성 한줄 정리

      • 일단 Heap에서 인스턴스를 만들고, Stack에서 참조값들을 저장하고 있음, Class 영역은 미리 정보를 가지고 있음
  • 객체 내부값 호출

    public class Main {
        public static void main(String[] args) {
    
        Car redCar = new Car("red"); // 생성자를 통해 객체 생성
        System.out.println(redCar.color); // red / redCar의 color 값을 불러옴
        redCar.go(); // 가즈아! / redCar의 매서드 go를 실행
    }
    
    class Car{
        // 필드
        public String color;
    
        // 생성자
        public Car(String color) {
            this.color = color;
        }
    
        // 메서드
        void go(){
            System.out.println("가즈아!");
        }
    }

◎ 필드

  • 필드 : 클래스에 포함된 변수

    • 클래스 변수(cv, class variable, static 변수): 같은 클래스끼리 공유하는 변수

      • 인스턴스를 만들지 않아도 해당 값을 할당 가능
      • 클래스명.클래스_변수 의 형태로 할당 가능
      • 객체.클래스_변수 형태로도 가능은 하지만 추천하지 않음
    • 인스턴스 변수(iv, instance variable): 인스턴스마다 가지는 고유한 값

      • 인스턴스를 만들고, 해당 객체에 값을 할당 (생성자 등을 통해)
      • 객체.인스턴스_변수 의 형태로 할당 가능
    • 지역 변수(lv, local variable) : 특정 범위 { } 안에서만 사용 가능

    class Example { // => 클래스 영역
        int instanceVariable; // 인스턴스 변수
        static int classVariable; // 클래스 변수(static 변수, 공유변수)
    
        void method() { // => 메서드 영역
            int localVariable = 0; // 지역 변수. {}블록 안에서만 유효
        }
  • 필드 사용 예시

    public class MyClass {
        public static void main(String args[]) {
            MathCompanyPeople people1 = new MathCompanyPeople("Steve Lee");
            MathCompanyPeople people2 = new MathCompanyPeople("Jim Kim");
    
            // 클래스이름.클래스변수 형태로 값을 설정
            MathCompanyPeople.companyName = "MATHCompany";
            System.out.println(people1.companyName); // MATHCompany
            System.out.println(people2.companyName); // MATHCompany
    
            people1.companyName = "MATHCOMPANT"; // 해당 표현은 추천하지 않음 (공용변수임 뚜렷히 안나타남)
            System.out.println(people1.companyName); // MATHCOMPANT
            System.out.println(people2.companyName); // MATHCOMPANT
    
            // 인스턴스 변수는 변경시 다른 인스턴스에게 영향을 주지 않음
            people1.name = "Gwichan Lee";
            System.out.println(people1.name); // Gwichan Lee
            System.out.println(people2.name); // Jim Kim
        }
    }
    
    class MathCompanyPeople{
        static String companyName = "MathCompany"; // Class 변수
        String name; // Instance 변수
    
        // 생성자
        MathCompanyPeople(String name){
            this.name = name;
        }
    }

◎ 매서드

  • 매서드 : 특정 작업을 수행하는 일련의 명령문들의 집합

    // 기본 형태
    자바제어자 반환타입 메서드명(매개 변수) { // 메서드 시그니처
        메서드 내용 // 메서드 바디
    }
    
    public class Prac{
        // static : 메인 Method 에서 실행하려면, 반드시 static이 있어야 한다.
    
        // 파라미터 X, 반환값 X
        public static void simplePrint() {
            System.out.println("파라미터도 없고, 반환값도 없어요!");
        }
    
        // 파라미터 O, 반환값 X
        public static void simpleSum(int num1, int num2) {
            System.out.println("num1 :" + num1 + ", num2: " + num2);
        }
    
        // 파라미터 X, 반환값 O
        public static int simpleReturn() {
            return 3;
        }
    
        // 파라미터 O, 반환값 O
        public static int sum(int num1, int num2) {
            return num1 + num2;
        }
    }
  • 매서드 호출

    • 매서드를 호출하기 위해서는 인스턴스 생성후, 호출
      (static 이 붙은 메서드는 인스턴스 생성없이 클래스 이름으로만 호출 가능)
    • 클래스 내부에있는 메서드끼리는 인스턴스 생성없이 호출 가능
    • ( ) 안의 인자(argument)는 순서와 type을 맞추어 넣어주어야 한다.
    System.out.println(Prac.simpleReturn());
    Prac prac = new Prac();
    System.out.println(prac.sum(3,4)); // 7
    System.out.println(prac.simpleReturn()); // 3
  • 매서드 오버로딩

    • 매서드의 이름이 같으면서 매개변수의 타입 or 개수가 다른 경우
    • 장점 : 하나의 이름의 매서드로 여러 경우의 수를 해결할 수 있다.
    • 예시 println / 타입이 모두 달라도, 같은 이름으로 호출할 수 있다.
    // println이 포함된 class 일부
    ...
    public void println(boolean x) {
          synchronized (this) {
              print(x);
              newLine();
          }
      }
    
      public void println(char x) {
          synchronized (this) {
              print(x);
              newLine();
          }
      }
    
      public void println(int x) {
          synchronized (this) {
              print(x);
              newLine();
          }
      }
     ...

◎ 생성자

  • 생성자 : 인스턴스가 생성될 때, 호출되는 인스턴스 변수 초기화 매서드 (일종의 메서드)

    • ※ 주의 : 생성자를 통해서 인스턴스를 생성하지만, 인스턴스를 생성하는 역할을 하지는 않음 (인스턴스를 생성하는 역할은 new 키워드가 함)
  • 특징

    • 메서드 이름을 Class 이름과 동일하게 해야함
    • return 을 가지지 않음 (따로 메서드 이름 앞에 타입을 작성하지 않음, void도 작성 X)
    • 따로 지정해주지 않으면, 자바 컴파일러가 기본 생성자를 자동으로 추가
    • 오버로딩이 가능함
    class MathCompanyPeople{
    
      static String companyName = "MathCompany"; // Class 변수
      String name; // Instance 변수
      int age;
      
      // 기본 생성자
      MathCompanyPeople() {} // field 값들이 기본값으로 하고 인스턴스가 생성됨 ex) String은 null ..
      
      // 생성자
      MathCompanyPeople(String name, int age){
          this.name = name;
          this.age = age;
      }
      
      // 생성자 오버로딩
      MathCompanyPeople(String name){
         this.name = name;
      }
      
    }
  • this.

    • 만들어진 해당 객체 안에서 field값을 불러올 때, " this.변수 " 의 형태로 사용

    • 일반적인 경우에는 생략이 가능하다.

      • 일반적인 경우에는 컴파일러에서 " this. " 부분을 추가해줌
      • Class의 field 변수와 메서드 내의 지역변수의 이름이 같을 경우, 구분해서 사용해주어야 한다.
      • 대체적으로 메서드(생성자)를 지역 변수명과 필드명을 동일하게 하여 작성하기 때문에 " this. " 를 구분해서 적어주어야 한다.
  • this() : 생성자 내부에서 오버로드 된 다른 생성자를 호출하는 방법

    • 조건
      1. 생성자 내부에서 사용 가능
      2. 반드시 생성자 첫줄에 사용해야함
    • 생성자는 오버로드가 가능하므로 매개변수의 타입, 개수에 따라 해당하는 생성자가 호출됨
    public class Main{
      public static void main(String[] args) {
    
        MathCompanyPeople people1 = new MathCompanyPeople();
        // 기본 생성자 호출!
        MathCompanyPeople people2 = new MathCompanyPeople("gwichan Lee", 25);
        // 생성자 두번째꺼 호출
        // 기본 생성자 호출!
        people2.printInfo();
        // 이름: gwichan Lee / 나이: 25
      }
    }
    
    class MathCompanyPeople{
    
      String name;
      int age;
    
      MathCompanyPeople() {
          System.out.println("기본 생성자 호출!");
      } 
    
      MathCompanyPeople(String name, int age){
          this();  // 같은 매서드 이름(생성자)을 가진 바로 위의 생성자를 호출함
    
          // Class의 field 변수와 메서드 내의 지역변수의 이름이 같을 경우, 반드시 this.  붙여 구분함
          this.name = name;
          this.age = age;
    
          System.out.println("생성자 두번째꺼 호출");
      }
    
    
      void printInfo(){
          System.out.print("이름: " + name); // this. 생략
          System.out.print(" / 나이: " + Integer.toString(this.age)); // field값을 불러올 때, " this.변수 " 의 형태로 사용
      }
    }
profile
배운 것은 기록하자! / 오류 지적은 언제나 환영!

0개의 댓글