[Java의 정석] 객체지향개념 1 (OOP 1)

Shiba·2023년 5월 26일
post-thumbnail

📓 객체지향개념 1 (OOP 1)

📕 객체와 클래스 (Object and Class)

📃 객체의 정의

- 실제로 존재하는 것. 사물 또는 개념
- 용도 : 객체가 가지고 있는 기능과 속성에 따라 다름.

📃 객체의 구성 요소

객체 = 속성(변수) + 기능(메소드)

ex) TV의 속성과 기능

속성기능
크기, 길이, 높이, 색상, 볼륨, 채널 ...켜기, 끄기, 볼륨 높이기, 볼륨 낮추기, 채널 변경하기 ...
class TV {
	//속성(변수)
	String color; //색상
    boolean power; //전원상태
    int channel; //채널
    
    //기능(메소드)
    void power() { power = !power; } //전원 켜기/끄기
    void channelUp() { channel++; } //채널 올리기
    void channelDown() { channel--; } //채널 내리기
}

📃 객체와 인스턴스

  • 객체

    모든 인스턴스를 대표하는 일반적 용어

  • 인스턴스

    특정 클래스로부터 생성된 객체
          ex) TV인스턴스, 붕어빵인스턴스 ...

📃 객체의 생성과 사용

🔹 객체의 생성

클래스명 변수명;
변수명 = new 클래스명();

Tv t; // Tv클래스 타입의 참조변수 t를 선언
t = new Tv(); //Tv인스턴스를 생성 후, 생성된 Tv인스턴스의 주소를 t에 저장

🔹 객체의 사용

변수명.멤버변수명 : 멤버변수 사용.
변수명.메소드(값1,값2,값3, ...); : 메소드 호출.

t.channel = 7; //Tv인스턴스의 멤버변수 channel의 값을 7로 초기화.(Tv채널 7번 틂)
t.channelDown(); //Tv인스턴스의 메소드 channelDown()을 호출.(Tv채널 한칸 내리기)
System.out.println("현재 채널은 " + t.channel + "입니다."); //현재 채널 출력

  • 하나의 인스턴스 - 여러 개의 참조변수 (가능)
  • 여러 인스턴스 - 하나의 참조변수 (불가능) - 변수는 하나의 값만 저장가능.
Tv t1 = new Tv();
Tv t2 = t1; //t1, t2둘다 하나의 인스턴스를 가리킴.

Tv t1 = new Tv(); //인스턴스 생성
Tv t2 = new Tv(); //인스턴스 생성
t2 = t1;//t2가 초기화한 인스턴스는 사라지고, t1, t2둘다 하나의 인스턴스를 가리킴

📃 객체 배열

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

Tv tv1, tv2, tv3; ->  Tv[] tvArr = new Tv[3];

//초기화
tvArr[0] = new Tv();
tvArr[1] = new Tv();
tvArr[2] = new Tv();

or

Tv tvArr = { new Tv(), new Tv(), new Tv() };

📃 클래스의 정의

🔹 정의 1

- 객체를 정의해 놓은 것 (설계도)
- 용도 : 객체를 생성하는데 사용

클래스객체
제품 설계도제품
TV 설계도TV
붕어빵 기계붕어빵

🔹 정의 2

클래스 == 데이터 + 함수

🔹 정의 3

클래스 == 사용자 정의 타입
💡 사용자 정의 타입 : 원하는 타입직접 만들 수 있다.

//시간 - 시, 분, 초 변수 생성
int hour1, hour2, hour3;
int minute1, minute2, minute3;
int second1, second2, second3;

- 필요한 시간이 많아질수록 번거롭다!

//클래스를 통해 시간 타입을 직접 생성
class Time {
	int hour;
    int minute;
    int second;
}

Time t1 = new Time();
Time t2 = new Time();
Time t3 = new Time();

- 필요한 시간만큼 객체를 생성하면되니 더 효율적이다!

//객체 배열을 통한 초기화
Time t = new Time[3];
for(int i = 0; i<t.length; i++){
	t[i] = new Time();
}

- 객체 배열을 사용하면 더 효율적!

📃 한 파일에 여러 클래스 작성

  • public class가 있는 경우, 소스파일의 이름은 반드시 public class의 이름과 대소문자까지 일치해야한다.
  • public class가 하나도 없는 경우, 소스파일의 이름아무 클래스 이름이여도 된다.
//Hello2.java
public class Hello2 {} //소스파일이름과 대소문자 까지 일치!
class Hello3 {}

//Hello2.java
class Hello2 {}
class Hello3 {} 
//둘중 아무 클래스 이름과 일치하면된다. (Hello3.java도 가능)


//잘못된 작성법

//Hello2.java
public class Hello2 {} 
public class Hello3 {}
//public class가 둘 이상이 존재하면 안된다. 최대 1개만 존재해야한다.
//(public class Hello3 -> class Hello3) or (Hello3.java파일에 Hello3 옮기기)

//Hello3.java
public class Hello2 {} 
class Hello3 {}
//public class의 이름과 소스파일의 이름이 일치하지 않는다. 
//(Hello3.java -> Hello2.java)

//hello2.java
public class Hello2 {} 
class Hello3 {}
//public class의 이름과 대소문자까지 일치해야한다. 
//(hello2.java -> Hello2.java) or (Hello2 -> hello2)

📔 변수와 메소드

📃 변수

🔷 선언 위치에 따른 변수 종류

변수의 종류선언위치생성시기
클래스 변수
(class variable)
클래스 영역클래스가 메모리에 올라갈 때
인스턴스 변수
(instance variable)
클래스 영역인스턴스가 생성되었을 때
지역 변수
(local variable)
클래스 영역 이외의 영역
(메소드, 생성자, 초기화 블럭 내부)
변수 선언문이 수행되었을 때
class Variables {
	int iv; //인스턴스 변수 
    - 인스턴스 마다 따로 초기화됨. (개별 속성)
    
    static int cv; //클래스 변수 
    - 같은 클래스의 인스턴스들은 모두 공유. (공통 속성)
    
    void method(){
    	int iv = 0; // 지역변수 
        - 메소드가 실행하지 않으면 초기화 되지 않음.
        - 메소드가 종료될 시 사라지는 변수
    }
}

🔹클래스 변수와 인스턴스 변수

  • 클래스 변수

    인스턴스들의 공통 속성

  • 인스턴스 변수

    인스턴스들의 개별 속성

ex) 포커 카드 객체
공통 속성 : 카드의 폭, 카드의 높이
개별 속성 : 카드의 문양, 카드의 숫자

class Card {
	//클래스 변수(cv). static 붙여주기
	static int width; // 폭
    static int height; // 높이
    
    //인스턴스 변수(iv)
    int number; // 숫자
    String kind; // 문양
}

🔹변수의 초기화, 멤버변수의 초기화

  • 변수의 초기화

    - 지역변수(lv)수동 초기화 해야함(사용전에 꼭!!)
    - 멤버변수(iv, cv)자동 초기화된다.

class initTest{
	int x; //인스턴스변수
    int y; //인스턴스변수
    //x,y는 자동으로 기본값(0)으로 초기화.
    
    void Method() {
    	int i; //지역변수
        int j = i; //에러!! 지역변수를 초기화하지 않고 사용
    }
}
  • 멤버변수의 초기화
  1. 자동 초기화

    인스턴스변수, 클래스변수는 자동 초기화된다.

  2. 간단 초기화

    • 명시적 초기화(=)
    class Car{
    	int door = 4; //기본형 변수의 초기화
      Engine e = new Engine(); //참조형 변수의 초기화 - 기본값이 없으므로 초기화 해야 함
    }
  3. 복잡 초기화

    • 초기화 블럭
      • 인스턴스 초기화블럭 : { }
      • 클래스 초기화 블럭 : static { }

    • 생성자

📃 메소드(Method)

🔹 정의

- 문장들을 묶어놓은 것.
- 작업단위로 문장들을 묶어서 이름 붙인 것.
- 값을 받아서 처리하고, 결과를 반환.

🔹 장점

  1. 코드의 중복을 줄일 수 있다.
  2. 코드의 관리가 쉽다.
  3. 코드를 재사용할 수 있다.
  4. 코드가 간결해서 이해하기 쉬워진다.

🔹 메소드 작성

메소드 = 선언부 + 구현부

  • 반복적으로 수행되는 여러 문장을 메소드로 작성
  • 하나의 메소드하나의 기능만 수행하도록 작성
반환 타입 메소드 이름 (매개변수 선언) { //선언부
	//구현부
	//수행할 내용  
    return 반환타입의 값;
}


int add(int x, int y){ //선언부
	//구현부
	int result = x + y; //지역변수(lv)
    
    return result; //int값 반환
}

🔹 메소드의 호출

메소드이름(값1,값2,값3, ...);

print99dan(); // void print99dan()호출. 매개 변수가 필요 없으니 빈 괄호
int result=add(3, 5); //int add(int x,int y)를 호출, result에 결과 반환

🔹 메소드의 실행흐름

  1. main메소드에서 add메소드를 호출한다. 인수 1L과 2L이 메소드 add의 매개변수 a, b에 각각 복사(대입)된다.
  2. 메소드 add의 괄호{ }안에 있는 문장들이 순서대로 수행된다.
  3. 메소드 add의 모든 문장이 실행되거나 return문을 만나면, 호출한 메소드(main메소드)로 되돌아와서 이후의 문장들을 실행한다.

🔹 return문

실행중인 메소드종료하고 호출한 곳으로 되돌아간다.

void printGugudan(int dan) {
	if(!(2 <= dan && dan <= 9))
    	return; // dan의 값이 2 ~ 9가 아닌 경우, 호출한 곳으로 되돌아감.
    
    for(int i = 1; i<=9; i++){
    	System.out.printf("%d * %d = %d\n" , dan, i, dan*i);
    }
    return; // 반환 타입이 void이므로 생략가능. 컴파일러가 자동 추가.
}

❗ 반환타입이 void가 아닌 경우, 반드시 return문이 필요하다.

int multiply(int x, int y){
	int result = x * y;
    
    return result; // 반환 타입이 void가 아니므로 생략 불가.
}

int max(int a, int b){
	if(a > b)
    	return a; //조건식이 참일 때만 실행.
        
    // 거짓일때의 리턴값이 없기때문에 에러가 발생
}

//다음과 같이 수정
int max(int a, int b){
	if(a > b)
    	return a; //조건식이 참일 때만 실행.
   	else
    	return b; //조건식이 거짓일 때 실행
}

❗ 반환 값은 타입이 일치(자동 형변환이 가능)해야한다.

🔸 호출스택

💡 스택(stack) : 밑이 막힌 상자. 위에 차곡차곡 쌓인다. (자료구조에서 학습)

  • 호출스택

- 메소드 수행에 필요한 메모리가 제공되는 공간.
- 메소드가 호출되면 호출스택에 메모리 할당. 종료되면 해제.
  맨 위의 메소드 하나만 실행. 나머지는 대기중

public static void main(String[] args){
	System.out.println("Hello");
}

🔹 기본형 매개변수와 참조형 매개변수

  • 기본형 매개변수

    - 변수의 값을 읽기만 할 수 있다. (read only)
    - 변수의 기본형 8가지를 자료형으로 가지는 매개변수

class Data { int x; }

class Ex6_6 {
	public static void main(String[] args) {
    	Data d = new Data(); //객체 생성
        
        d.x = 10; // x를 10으로 설정.
        System.out.println("main() : x = " + d.x);
        
        change(d.x); //change() 호출
        System.out.println("After change(d.x)");
        
        //기본형 매개변수는 읽기만 가능하므로 d.x는 그대로 10이 출력
        System.out.println("main() : x = " + d.x); //10이 출력됨
    }
    
    static void change(int x) {// 기본형 매개변수 int x
    	x = 1000; //x를 1000으로 변경
        System.out.println("change() : x = " + x);
    }
}
  • 참조형 매개변수

    - 변수의 값을 읽고 변경할 수 있다. (read & write)
    - 기본형을 제외한 나머지를 자료형으로 가지는 매개변수

class Data { int x; }

class Ex6_7 {
	public static void main(String[] args) {
    	Data d = new Data(); //객체 생성
        
        d.x = 10; // x를 10으로 설정.
        System.out.println("main() : x = " + d.x);
        
        change(d.x); //change() 호출
        System.out.println("After change(d.x)");
        
        //참조형 매개변수는 주소를 저장하고있기 때문에 1000으로 변경되어있음 
        System.out.println("main() : x = " + d.x); //1000이 출력됨.
    }
    
    static void change(Data d) {// 참조형 매개변수 Data d
    	d.x = 1000; //d.x의 주소에 저장된 10이 1000으로 변경.
        System.out.println("change() : x = " + d.x);
    }
}
  • 참조형 반환타입
class Data { int x; }

class Ex6_8 {
	public static void main(String[] args) {
    	Data d = new Data(); //객체 생성
        
        d.x = 10; // x를 10으로 설정.
        
        Data d2 = copy(d); // 반환된 객체주소를 받음.
        System.out.println("d.x =" + d.x); // 10이 출력.
        System.out.println("d2.x ="+d2.x); // 같은 10이 출력.
    }
    
    static Data copy(Data d){ // 반환타입이 참조형 매개변수 Data
    	Data tmp = new Data(); // 새로운 객체 tmp 생성.
        
        tmp.x = d.x; // d.x의 값을 tmp.x에 복사.
        
        return tmp; // 복사한 객체의 주소를 반환.
    }
}

🔹 인스턴스 메소드와 static 메소드

  • 인스턴스 메소드

    - 인스턴스 멤버(iv, im)와 관련된 작업을 하는 메소드
    - 인스턴스 생성 후, 참조변수.메소드이름() 으로 호출
    - 메소드 내에서 인스턴스변수(iv) 사용가능

  • static 메소드

    - 인스턴스 멤버(iv, im)와 관련없는 작업을 하는 메소드
    - 객체생성없이 클래스이름.메소드이름() 으로 호출
    - 메소드 내에서 인스턴스변수(iv) 사용불가

class MyMath{
	long a, b; //인스턴스변수(iv)
    
    long add() { //인스턴스 메소드 (인스턴스변수(iv)를 사용)
    	return a + b;
    }
    
    static long add(long a, long b) { // 클래스 메소드 (static 메소드)
    	return a + b; // 지역변수(lv)를 사용
    }
}

////////////////////////////////////////////////////////////////////

class MyMathTest {
	public static void main(String[] args) {
    	System.out.println(MyMath.add(200L,100L)); //클래스 메소드 호출 
        - 객채생성 없이 호출가능. 인스턴스 변수 사용불가
        
        MyMath mm = new MyMath();
        //인스턴스 변수 초기화
        mm.a = 200L;
        mm.b = 100L;
        
        System.out.println(mm.add()); //인스턴스 메소드 호출
        -인스턴스 생성 후 호출가능. 인스턴스 변수 사용가능.
    }
}

❗ 가장 중요한 차이는 인스턴스 멤버(iv, im) 사용가능 여부!

class TestClass {
	int iv; //인스턴스 변수
    static int cv; //클래스 변수
    
    void instanceMethod() { //인스턴스 메소드
    	System.out.println(iv); //인스턴스 변수를 사용할 수 있다.
        System.out.println(cv); //클래스 변수를 사용할 수 있다.
    }
    
    static void staticMethod() { // static 메소드
    	System.out.println(iv); //에러!! 인스턴스 변수를 사용할 수 없다.
        System.out.println(cv); // 클래스 변수는 사용할 수 있다.
    }
}
class TestClass {
    void instanceMethod() { //인스턴스 메소드
    	//...
    }
    
    static void staticMethod() { // static 메소드
    	//...
    }
    
    void instanceMethod2() { //인스턴스 메소드
    	instanceMethod(); //다른 인스턴스 메소드를 호출
        staticMethod(); //static 메소드를 호출
    }
    
    static void staticMethod2() { //static 메소드
    	instanceMethod(); //에러!! 인스턴스 메소드를 호출할 수 없다.
        staticMethod(); //static 메소드는 호출가능.
    }
}

📘 메소드 오버로딩(Overloading)

📃 정의

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

ex)

void println()
void println(boolean x)
void println(char x)
void println(char[] x)
void println(int x)
void println(long x)
void println(float x)
void println(double x)
void println(Object x)
void println(String x)

📃 성립 조건

  1. 메소드 이름이 같아야 한다.
  2. 매개변수의 개수 또는 타입이 달라야 한다.
  3. 반환타입은 영향이 없다.
int add(int a, int b) { return a + b; }
int add(int x, int y) { return x + y; }
//두 메소드는 같은 메소드로 취급. (오버로딩 X)

int add(int a, int b) { return a + b; }
long add(int a, int b) { return (long)(a + b); }
//반환타입은 영향이 없기 때문에 같은 메소드로 취급. (오버로딩 X)

long add(int a, long b) { return a + b; }
long add(long a, int b) { return a + b; }
//a 와 b 의 타입이 각각 다르므로 다른 메소드. (오버로딩 O)

🔷 예제

class MyMath {

	int add(int a, int b) {
    	System.out.print("int add(int a, int b) - ");
        return a+b;
    }
    
    long add(long a, long b) {
    	System.out.print("long add(long a, long b) - ");
        return a+b;
    }
    
    int add(int[] a) { //배열 모든 요소의 합을 결과로 돌려준다.
    	System.out.print("int add(int[] a) - ");
        int result = 0;
        for(int i = 0; i<a.length; i++)
        	result += a[i];
            
        return result;
    }
}

📘 생성자

📃 정의

- 인스턴스생성될 때마다 호출되는 인스턴스 초기화 메소드
- 인스턴스 생성시 수행할 작업(보통 iv 초기화)에 사용

📃 작성

- 이름이 클래스이름과 같아야한다.
- 리턴값이 없다.(void 안붙임)
- 모든 클래스반드시 생성자를 가져야 한다.

클래스이름(타입 변수명, 타입 변수명, ...) {
              //인스턴스 생성시 수행될 코드
             //주로 인스턴스 변수의 초기화 코드를 적는다.
}

class Card {

	//매개변수 없는 생성자
	Card() { //클래스이름()
    	//인스턴스 초기화 작업
    }
    
    //매개변수 있는 생성지
    Card(String kind, int num){ // 클래스이름(타입 변수명, 타입 변수명)
    	//인스턴스 초기화 작업
    }
}

🔷 기본생성자

- 매개변수없는 생성자
- 생성자하나도 없을 때만, 컴파일러가 자동 추가

  class Data_1 {
	  int val;
  }
  
  class Data_2 {
	  int val;
    
      Data_2(int x){
      	val = x;
      }
  }
  
  class EX6_11{
  	public static void main(String[] args){
    	//생성자가 없어서 컴파일러가 자동 추가
    	Data_1 d1 = new Data_1();
        
        //compile error - 매개변수 있는 생성자가 존재
        Data_2 d2 = new Data_2(); 
    }
  }

📘 this와 this()

📃 생성자 this()

🔷 정의

- 생성자에서 다른 생성자 호출할 때 사용
- 다른 생성자 호출첫 줄에서만 사용가능

class Car {
	String color;
    String gearType;
    int door;
    
    Car(){
    	this("white", "auto", 4); //생성자 this()사용
    }
    
    Car(String color){
    	this(color, "auto", 4); //생성자 this()사용
    }
    
    Car(String gearType){
    	door = 5;
    	this("white", gearType, 4); //에러!! 두번째 줄에서는 사용불가
    }
    
    Car(String color, String gearType, int door){ //생성자 this()의 목적지
    	this.color = color;
        this.gearType = gearType;
        this.door = door;
    }
}

📃 참조변수 this

🔷 정의

- 인스턴스 자신을 가리키는 참조변수
- 인스턴스 메소드(생성자 포함)에서 사용가능
- 지역변수인스턴스 변수구별할 때 사용

Car(String c, String g, int d){ 
	//color는 인스턴스 변수, c는 지역변수 
    //같은 클래스내이기 때문에 this생략 가능
    	color = c;
        gearType = g;
        door = d;
 }


Car(String color, String gearType, int door){
	//this.color는 인스턴스 변수, color는 지역변수
    //this가 없으면 지역변수와 구별 불가능. - this 생략불가
    	this.color = color;
        this.gearType = gearType;
        this.door = door;
 }

this()this는 완전히 다른 것이다. this()는 생성자이고, this는 참조변수이다.

profile
모르는 것 정리하기

0개의 댓글