language/java

6. oop(object-oriented Programming) 객체지향 프로그래밍

wooweee 2023. 3. 3. 16:20
728x90

01. 객체지향 언어

  • 핵심 개념: 캡슐화, 상속, 추상화, 다형성
  • 객체지향 언어는 기존 프로그래밍 언어에 몇 가지 새로운 규칙을 추가한 것
    1. 코드의 재사용성 높고
    2. 유지보수가 용이
    3. 중복 코드 제거

 

02. class 와 object

  1. class: object의 설계도 또는 틀, object를 생성에 사용
    1. 설계도
    2. 변수 + 메서드
    3. 사용자 정의 타입
  2. object: 실제로 존재하는 것, 서로 관련된 변수의 묶음  + 메서드(실제 메서드는 객체에 존재하지 않는다.)
  • 프로그래밍 순서: class 작성 후 class로부터 object를 생성하여 사용한다.

 

03. object 구성요소 - property(속성) 과 function(기능)

  • object: 속성 + 기능
    • 둘 중 하나만 있어도 상관없다.
  • member: object가 가지는 속성과 기능을 멤버라고 한다.
    • 속성 = variable = property = field = member 변수
    • 기능 = method
class Tv{

// variable = property = field
String color;
boolean power;

// method = function
void power () { power = !poewer; }
void channelUp () {channel++;}

}

 

04. object and instance

  • 인스턴스화: class로부터 객체를 만드는 과정
  • 인스턴스: class로부터 만들어진 객체
  • 어감차이 일뿐 같은 의미
    • 책상은 객체이다 (o)    책상은 인스턴스다(x)
    • 책상은 책상 클래스의 인스턴스이다 (o)  책상은 책상 클래스의 객체이다 (o)

 

05. 한 파일에 여러 클래스 작성하기

  • 관례적으로 class 명은 첫 character를 대문자로 작성한다.  ex) Hello.java
파일명 옳은 예  
hello2.java public class hello2 {}
            class hello3 {}
public class가 있는 경우, 소스파일의 이름은 반드시 public class의 이름과 일치해야함
hello2.java class hello2 {}
class hello3 {}
public class가 하나도 없는경우 소스파일의 이름은 아무거나 가능하다
     
파일명 잘못된 예  
hello2.java public class hello2 {}
public class hello3 {}
하나의 소스파일에 public class가 2개 이상은 안된다.
hello2.java public class hello3 {}
            class hello2 {}
소스파일의 이름은 반드시 public class의 이름과 일치해야함
hello2.java public class Hello2 {}
            class hello3 {}
대 소문자 까지 일치해야한다.

 

06. 객체의 생성과 사용 

Tv t = new Tv();
class_type 변수명 = 객체생성 생성자;
  •  순서
    1. Tv t;
      • 참조변수 생성 = class 설계도를 참조하기 위한 변수
      • object memory 주소와 연결 -> 리모컨 역할 수행
      • 오직 참조변수를 통해서만 object(==instance)를 다룬다.
    2. t = new Tv();
      1. new
        • Tv class를 토대로 Tv object가 메모리의 빈 공간에 생성
        • Tv object 가 저장된 memory 주소는 참조변수 t와 동일
      2. Tv();
        • 객체 초기화
  • 주의
    • 참조변수와 객체는 다르다.  ' = ' 대입 연산자로 memory 주소만 연결될 뿐이다.

 

public class Main {
    public static void main(String[] args) {
    }

}

// class Name:  Main
// main method: public static void main(String[] args) {}
  • main method 사용 여부 - main method & new object & class 설계도 관계
    • main method: progrem 수행을 위해 꼭 필요한 class 이며 progrem이 시작되는 class
    • class NAME: main method가 NAME 설계도를 이용하여 Object를 만들기 위한 class
  • Tv 설계도 만으로는 스스로 Tv를 만들지 못하니 Tv 공장(main method)에서 설계도를 보고(class Tv)   object(new Tv()) 만든다.

 

 

07. 객체의 생성과 사용 - 객체가 여러개 일 때 

  • 참조변수 여러개가 하나의 객체의 주소와 연결이 가능하다
  • 참조변수 하나가 여러개 객체 주소와 연결은 불가능하다. -> 변수는 하나의 값만 저장이 가능하다. 
Tv t1 = new Tv(); // 0x100 주소의 객체 생성
Tv t2 = new Tv(); // 0x200 주소의 객체 생성

t2= t1 // t2의 주소를 0x200 -> 0x100으로 변경

하나의 객체에 참조변수 2개가 연결이 됨
+ first t2의 객체는 GC(garbage collector)가 제거하여 메모리 유지
  • 참고 자료
    1. class는 메모리의 어느 부분에 저장되는지
    2. class의 instance는 메모리의 어느 부분에 저장되는지
    3. instance의 참조변수는 메모리의 어느 부분에 저장되는지

Tv 클래스가 Card클래스(0xbbbb)라고 생각해서 보기

 

 

 

08. 객체배열 == 참조변수 배열

Tv[] tvArr = new Tv[3];
  1. 참조변수의 배열이 3개가 생성
  2. value는 자동초기화 값이 null
  3. array만 생성하고 new Tv[3]; 있지만 아직 instance=object는 생성안됨
Tv[] tvArr = { new Tv(), new Tv(), new Tv() };

Tv[] tvArr = new Tv[3];
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();
  1. 참조변수와 연결할 object 생성

 

09. class의 정의(1) - data & method 결합

  • class의 정의 3가지
    1. 객체를 생성하기 위한 틀 (== 설계도)
    2. 데이터와 함수의 결합 (== 변수, 메서드)
      •  data = variable = property  /  function = method 
    3. 사용자 정의 type

 

  • 변천사
    1. variable(변수): 하나의 data만 저장할 수 있는 공간
    2. array: 같은 타입 많은 데이터
    3. structure: 서로 관련된 여러 데이터를 종류에 관계없이 하나의 집합으로 저장할 수 있는 공간
    4. class: 데이터와 함수의 결합
      • ex) String. string은 char의 배열 + method 가 포함된 class 이다.

 

10. class의 정의(2) - 사용자 정의 타입

  • 사용자지정 타입(== 참조형 타입): 서로 관련된 변수들을 묶어서 하나의 타입으로 새로 추가하는 것
Time: 사용자 정의 타입, 참조형

class Time {
	int hour;
	int minute;
	float second;
}

class type 아닐 때

int hour;
int minute;
float second;

// 시계를 수십개를 만든다고 할 때

int hour1, hour2, hour3 ,,,,, ;
int minute1, minute2, minute3 ,,,,, ;
float second1, second2, second3 ,,,,, ;

// array로 바꿔도 시,분,초가 서로 분리되어 있기 때문에 프로그램 수행시 변수들이 뒤섞여서 틀린 데이터 될 가능성 있음
int[] hour = new int[10];
int[] minute = new int[10];
float[] second =new float[10];

 

11. 선언위치에 따른 변수의 종류

// class 영역: method 영역을 제외한 모든 부분
class 선언class {
    int iv;
    Static int cv;
    
    //method 영역
    void method(){
        System.out.print("method 영역에서는 다 들어올 수 있다.");
    }
}
  • class 영역 = main method가 없는 class의 method를 제외한 영역으로 선언문만 작성가능
    • x = y + 4;  안됨
    • System.out.print();  안됨
    • 변수 선언 & method 선언
      1. member variable - CV(class variable) / IV(instance variable) 존재
      2. method variable - LV(local variable)  존재
  • method 영역 : 선언문 포함 모든 것을 작성가능 하다
    • x = y + 4; 가능
    • System.out.print();  가능
class Name {
	// 변수 선언부
	int iv;
	Static int cv;

	// method 선언부
	void method(){
		int lv = 0;
    }
}
  • cv, iv, lv
    1. cv
      • static
      • 초기에 램에 올라가 있음 -> class 객체 생성 필요없이 사용 가능
      • 모든 instance가 공통된 저장 공간을 공유
    2. iv
      • instance 생성을 해야 존재함
      • object는 iv의 집합체
    3. lv
      • method 안에서만 존재하고 method 작업 끝날 시 사라진다.
      • params 또한 lv
      • for문 while문의 블럭 내에 선언된 지역 변수는 {} 안에서만 사용 가능하며, 블럭 벗어나면 소멸된다.

 

12, 13. class variable and instance variable

  • 조건
  • 카드를 분석해서 속성(변수)과 기능(method) = object 를 파악
    • iv: 카드의 개별 속성 - J,Q,K, ♡,♧,◆ 
    • cv: 카드의 공통 속성 - 폭, 높이

 

  • cv는 모든 instance가 하나의 저장공간을 공유하므로 항상 공통된 값을 가진다.
class Card {
	String kind;
	int number;

	static int width;
	static int height;
}


class 6-12 {
    public static void main(String[] args){
    Card c1 = new Card();
    Card c2 = new Card();

    // int 초기화
    c1.kind = "hear";
    c2.number = "2";

    // class 초기화
    c2.width = 100;  // Card.width = 100;
    c1.height = 80;  //Card.height = 80;

// -> c1,c2 object 모든 100, 80 값을 가진다. 
// 하지만 참조변수를 사용하면 헷갈리므로 좋지 않다. error가 생기는건 아님

}

그림으로 보기

 

14. method

  • method
    • 반복 사용되는 문장들을 묶은 것
    • 하나의 기능만 수행
    • 입력값과 출력값이 있을 수도 없을 수도 있다.

 

  • input -> [ black box ] -> output
    • input: 0~n개
    • output: 0~1개  * output n개(array or object 이용)

 

// method 예시
int 메서드이름 (int x, int y){    // 선언부 : int, 메서드이름, int x, int y 
    int result = x + y;       // 구현부
    return result;            // 구현부
}

// 선언부, 구현부와 별개로 int x, int y, int result 는 지역변수이다. lv
  • method 정의: 선언부 + 구현부
    •  선언부: 반환타입 메서드이름(params)
      • 반환값이 존재하지 않을 시 반환타입으로 void 작성
    •  구현부: { /* method 호출시 수행될 코드*/ }

 

  • method vs function
    • method: 객체지향개념의 함수로 class 안에 존재
    • function: 독립적

 

15. method 선언부

// 반환타입 method이름(params 선언){
       int add(int x, int y)
   }
  • params
    • params간 구분은 컴마(,) 사용
    • 타입 생략 불가
    • params 개수 제한 없음, 없으면 () 만 작성
    • 너무 많을 시 : arrays || 참조변수 이용
  • 반환타입
    • output value의 type 작성
    • return value(반환값)이 없을 시 return type은 void로 작성

 

16. method 구현부

// 리턴값은 선언문의 리턴타입과 동일해야함
int add(int x, int y){ // 리턴타입 int
   int result = x + y;
   return result; // 리턴 값
}

// void는 compiler가 자동으로 return; 넣어준다.
void method(){};
  1. method의 return 반환값 조건
    1. void 아닌 경우 반드시 return 포함
    2. return 값은 단 하나의 값만 반환 return은 해당 method를 종료하고 method를 부른 method에게 반환 값을 주는 것
    3. 반환값은 return type과 같거나 자동 형변환 가능한 것
  • 선언부의 params와 구현부의 result는 lv 이다.

 

17, 18. method 호출 및 실행 흐름

  • 메서드를 호출하기 위해선 출력값을 저장하기 위한 공간이 필요하다.
    void는 필요없다.
  • argument, params
    • argument: 인자, params에 넣을 실제 값
    • params: 매개변수, argument가 들어오면 params에 대입해주고 params의 역할을 수행하게 해준다.
  • 메서드 실행 흐름
    1. 객체 생성
    2. 메서드와 argument 확인
    3. 메서드 호출 및 argument를 params에 대입
    4. 리턴값 반환
public static void main(String[] args){
    ... // instance 생성 부분 생략
	
    int result = add(3,4); // add라는 method 호출
    add(1,2); // ok, but 반환값을 볼 수 없음
    ...
}

class Calculate {
    int add(int x, int y){
    return = x + y;
    }
}

/* argument 타입은 params의 타입과 동일하거나 자동 형변환 가능한 것이여야 한다.
add(3,4) // 3과 4는 argument
add(int x, int y) // int x, int y 는 params
*/

/* method 실행 흐름
1) instance 생성
2) argument 확인 -> 관련 method 호출  add(3,4) -> int add(int x, int y) method 호출
3) 반환값 반환 -> return = x + y = 7  -> int result = 7;
*/

 

20. return문

  • return문: 현재 실행중인 method를 종료하고 호출한 method(main method 쪽)로 돌아간다.
  • 모든 method에는 적어도 하나의 return문이 있어야 한다.
  • return type이 void일 경우에는 compiler가 자동으로 return; 만들어주므로 생략가능

 

int max(int a, int b){
   if(a>b) return a;
   else return b;
}
  • 조건문의 method: true, false 각각 return 값이 필요하다.

 

21. 반환값

반환값으로 변수 및 수식으로 작성가능 - return이 계산 후에 반환

int add (int x, int y) {
	int result = x + y;
	return result;

	return = x + y;
}

// 반환타입이 method일 때도 반환타입만 동일하면 상관없다.
int method1(int x, int y){
    Method2 method2 = new Method2();
    
    int result = method2(x-y);
    return result;
}

int method2(int x){
	return int x >=0 ? x:-x; // 반환값의 type이 method1과 동일하면 사용가능
}

 

 

22. call stack

  • 호출스택: method의 작업에 필요한 메모리 공간을 제공
  • 특징: method 수행 후 사용했던 메모리 반환 후 스택에서 제거 / 하나만 실행가능
    • method가 호출되면 수행에 필요한 만큼의 메모리를 스택에 할당받음, 탑쌓듯이 쌓은 후 메서드 작업 끝나면 사라진다.
    • return 이 있는 method 는 종료되면서 결과값을 자신을 호출한 method 에게 반환
  • 참고
    • Method Area: cv
    • Call Stack: lv
    • Heap: iv, instance

 

23~25 기본형 매개변수, 참조형 매개변수, 참조형 반환타입

기본형 매개변수: 변수의 값을 읽기만 할 수 있다.

참조형 매개변수: 변수의 값을 읽고 변경할 수 있다.

 

26, 28. static method와 instance method
27, 29. 교재 참조 191p

  • 참고
  • 설계도 class 일 때만 instance method 든지 class method인지 생성 가능. main(){} 에서는 안됨

 

  1. instance method
    • instance 생성 후, 참조변수.methodNAME();으로 호출
    • instance member(iv,im)와 관련된 작업 - iv를 사용, params 사용 가능
      • instance member는 static member 사용이 가능
      • instance member 존재 의미는 static member가 이미 memory에 존재한다는 의미
  2. static method
    • instance 생성 필요 X, classNAME.methodNAME();으로 호출
    • iv 사용불가 -> parameter 사용
      • iv의 묶음 이 instance로써 object가 존재해야만 iv 사용 가능하다.
      • static 사용시 object를 생성할 필요가 없으므로 iv 사용가능성이 ambiguous하다.

 

  • static method란 객체 생성 없이 호출가능한 method이다.
    • 언제 사용하나? iv를 사용하지 않는 method일 때 사용한다.

 

  • static vs instance with variable and method
    1. 변수
      • 개별 속성 = iv
      • 공통 속성 = cv = static
    2. 메서드
      • 기능 중 iv를 사용하는 method = im
      • iv를 사용하지 않는 method = cm = static
      •  공통, 개별로 method를 분류하지 않는 이유: method는 명령문의 집합으로 공통 개별의 개념 따윈 없다.

 

30. overloading 

오버로딩: 한 class 내에 같은 이름의 method를 여러개 정의 한 것  ex) println()

 

오버로딩 조건

  1. method 이름이 같아야 한다.
  2. parameter의 개수 or type이 달라야 한다. 변화하는 부분
  3. return type은 영향을 미치지 않는다. 상관없음
// println()

void println(boolean x);
void println(char x);
void println(char[] x);

// type 같음 error
int add(int a, int b){return a+b};
int add(int x, int y){return x+y};

// return은 영향X error
int add(int a, int b){return a+b};
long add(int a, int b){return (long)(a+b)};

// 애매한 것 문제는 없지만 만약에 add(3,3)하면 둘중 뭘 해야될지 몰라서 난리남
long add(long a, int b){return a+b};
long add(int a, long b){return a+b};

 

 

32. 생성자(constructor)

  • 생성자: instance가 생성될 때 호출되는 instance 초기화 method이다. = iv 초기화 method
  • 특징
    1. 생성자의 이름은 class 이름과 동일
    2. 생성자는 리턴값이 없다.
      • 생성자도 method이기 때문에 void를 붙여야 하지만 return 값이 없으므로 void 생략가능

예시

class Declaration {
// instance 설계도
    String color; // iv
    int number;   // iv

    Declaration () {};  // 기본 생성자

    Declaration(String color, int num) { // 매개변수 생성자
    color = color;
    number = num;
    }
}

class main {
	public sttic void main(Stirng[] args){
	
    // 기본 생성자 일때 - 초기화
    Declaration d = new Declaration(); 
    // object 생성 - new + 생성자 호출(= Declaratoin();)
    }
    d.color = "red";
    d.number = 12;

	// 매개변수 생성자 일때 - 초기화
	Declaration d = new Declaration("red", 12); 
    // 매개변수 생성자 호출 
}

 

33. 기본 생성자

  • 모든 class 에는 반드시 1개 이상의 생성자가 정의
  • class에 생성자가 하나도 없을 시 compiler가 자동으로 기본 생성자 classname() {}; 을 추가하여 compile 한다.
  • 1개의 생성자가 정의되면 최소 조건이 충족되었으므로 compiler는 기본 생성자를 자동으로 추가하지 않는다.
class Data_1{
    int value;
    // Data_1(){}; // 생성자가 하나도 없으므로 컴파일러가 자동으로 생성해준다.
}

class Data_2{
    int value;
    // Data_2(){}; -> 아래 매개변수 생성자가 있으므로 기본생성자는 내가 수동으로 입력해야만 한다.
    
    Data_2(int x) {
    value =x;
    }
}

class factory {
    public static void main(String[] args){
    Data_1 d1 =new Data_1(); // Data_1() - 생성자 호출 방법
    Data_2 d2 =new Data_2(); // error, 기본생성자가 있지 않기 때문
    }
}

 

 

34, 35. parameter 있는 생성자

class Car {
    String color;
    String name;
    int door;

    // parameter 생성자
    Car(String c, int d) {
    color = c;
    door = d;
    }

// parameter 생성자를 만들면 기본 생성자는 자동으로 안생기기 때문에 습관적으로 작성하기
    Car(){}
}


class main {
    public static void main(String[] args){
        Car c = new Car(); // 기본 생성자가 있기에 생성 가능 - 하지만 값을 지정하지 않았으므로 기본 초기화
        Car c1 = new Car("red",4); // params 생성자가 있기에 생성 가능
        c1.name = "benz"; // 안써도됨, null로 나올뿐
	}
}

 

  • Car c1 = new Car("red", 4); - 작동 원리
    1. c1 box 생성
    2. new: instance 생성 0x100 주소(box안에는 초기화 값 없음)
    3. Car("red", 4) 생성자 method 작동
    4. instance box에 argument 들어감 
    5. = 대입 연산자 작동
    6. c1 box 0x100 주소 가짐

 

36. this()

  • 생성자, 같은 class의 다른 생성자를 호출할 때 사용
  • 조건
    1. 생성자의 이름으로 class 대신 this를 사용한다
    2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 1st 줄에서만 호출 가능

 

class Car2 {
    String color;
    String gearType;
    int door;

    Car(){
        this("white", "auto", 4);
    }
    Car(String color){
        this(color, "auto", 5);
    }
    
    // this() 주인공
    Car(String c, String g, int d){
        color = c;
        gearType = g;
        door = d;
    }
}

class factory {
    public static void main(String[] args){
        Car c1 = new Car();
        Car c2 = new Car("red");
        System.out.println(c1) // white, auto, 4
        System.out.println(c2) // red, auto, 5
    }
}

 

37. this vs this()와 다름

  • this: instance 자신을 가리키는 참조변수, 인스턴스의 주소가 저장되어 있다.
  • 따로 선언 필요없이 사용가능
  • 모든 인스턴스메서드(im)에 지역변수(lv)로 숨겨진 채로 존재
  • this를 사용할 수 있는 것은 인스턴스멤버뿐이다. static에는 사용불가하다.
  • iv lv 구별할 때 사용
// params 와 iv 이름이 동일 할 때 혼란 방지용으로 사용

class Car {
    String color; // this.color 진짜이름
    int door; // this.door 진짜이름

    // parameter 생성자
    Car(String color, int door) {
        this.color = color;
        this.door = door;
    }
}

 

38. 변수의 초기화

  1. 지역 변수
    • 수동으로 초기화
    • method는 stack에 빠르게 올라가고 내려가는데 올릴때 마다 0으로 초기화 하면 프로그램 성능일 떨어짐
    • 수동으로 초기화 후 아예 stack에 덮어씌움
  2. 인스턴스 변수
    • 자동으로 초기화
    • object, array의 내용들을 하나하나 수동으로 지정하기에 부담이 크기 때문

 

39, 40. 멤버변수의 초기화 - iv, cv

  • 초기화 복잡도 순서
    1. 자동 초기화 
      • int x;
    2. 명시적 초기화
      • int x = 1;
      • 변수 선언과 동시에 초기화, 가장 우선적으로 고려
    3. 초기화 블럭
      • cv
        • static{초기화 블럭 };
      • iv
        • { 초기화 블럭}; - 거의 안씀
    4. 생성자

 

  • 초기화 순서
    1. cv → iv
      • class 가 처음 loading 될 때 한번만 초기화
      • 불변의 1등 초기화
      • instance가 생성될 때마다 초기화
    2. 자동 초기화  명시적 초기화  초기화 블록  생성자
      • 초기화 중복시 복잡도가 높은 것으로 덮어씌움