[11일차]JAVA OOP(객체지향 프로그래밍)

유태형·2022년 5월 10일
0

코드스테이츠

목록 보기
12/77

오늘의 목표

  1. 객체지향 프로그래밍(OOP)
  2. 클래스(Class)
  3. 객체(Object)
  4. 필드
  5. static
  6. 메서드
  7. 오버로딩



내용

OOP == 객체지향 프로그래밍
방법론 == SW를 어덯게 개발할지?

구조체 프로그래밍 -> 순서대로 계층적으로 설계
객체 지향 프로그래밍 -> Object를 통해 설계
애자일, 스크럼, DDD, MSA 등등...

OOP != Java

Object == 객체(이 세상 모든 물체)

Programming의 추상화는 실제 세상으 ㅣ객체를 명확하고, 핵심 위주로 단순화 하여 구체화




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

생물,물체 논리 같은 개념들도 모두 객체가 될 수 있습니다. 프로그래밍에서는 모든 실제 하는 대상객체(Object)라고 부릅니다. 객체지향의 핵심은 세상은 모든 개체들로 이루어 져 있으며 모든 사건의 시작은 개체들간의 상호 작용으로부터 시작된다고 보는 것입니다. 프로그래밍에서는 순서에 맞게 정렬된 명령어들의 집합인 절차적 프로그래밍과 다르게 속성과 기능을 변수와 함수로 정의한 객체를 만들어 객체들간 데이터를 주고 받는 객체 지향형 프로그래밍 입니다.

객체는 식별자, 상태, 메서드, 클래스로 선언 및 사용 가능합니다.

참고자료 : http://wiki.hash.kr/index.php/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5




클래스(Class)

클래스는 객체를 정의한 설계도 또는 틀입니다. 클래스는 객체가 아닙니다. 마찬가지로 객체 또한 클래스가 아닙니다. 하지만 객체는 클래스에서 정의된 설계로만 만들 수 있습니다.

클래스는 그 자체로 객체가 아닌 객체를 생성하는 하나의 틀일 뿐 입니다. 예로 들겠습니다. TV설계 도면은 TV를 만들 수 있게 해주는 것이지 도면이 TV자체가 될 수는 없습니다. 또 하나의 예를 하나 더 든다면 붕어빵의 틀은 붕어빵을 만들 수 있게 해주지만 그 자체로 붕어빵이 될 수는 없습니다. TV도면, 붕어빵 틀 = 클래스, TV, 붕어빵 = 객체로 생각하시면 됩니다.

클래스에 정의된 대로 객체를 만들 수 있다면, 객체를 만드는 행위는 인스턴스화라고 부르고 해당 클래스를 통해 생성된 객체를 클래스의 인스턴스(instance)라고 합니다.

클래스를 인스턴스화 하여 객체를 만들고 객체들간 데이터를 주고 받는 것이 객체 지향형 프로그래밍이라면 잘 짜여진 객체 지향형 프로그래밍은 클래스를 잘 짜는것이 중요합니다.



클래스의 구성요소, 기본문법

클래스는 class키워드를 사용하여 정의합니다. 클래스명은 관례적으로 대문자로 시작합니다.

//클래스 정의
class 클래스{
	//필드,메서드,...
}

클래스 내부에서 정의해 보겠습니다.

public class ExampleClass{
	int x = 10; //필드
	void printX(){...} //메서드
	ExampleClass(..){...} //생성자
	class InnerClass { ...} //이너 클래스

필드 : 클래스의 속성을 나타내는 변수입니다.
메서드 : 클래스의 기능을 나타내는 함수입니다.
생성자 : 클래스의 객체를 생성하는 역할을 수행합니다.
이너 클래스 : 클래스 내부의 클래스를 나타냅니다.

자바의 클래스는 선언 위치에 따라 종류가 구분됩니다. 위치에 따라 일반 클래스, 중첩 클래스, 내부 클래스, 지역 클래스, 익명 클래스, 추상 클래스가 존재합니다.

출처 : http://wiki.hash.kr/index.php/%ED%81%B4%EB%9E%98%EC%8A%A4

일반 클래스 : 선언위치는 파일의 시작부분이며 일반 클래스를 생성하려는 목적으로 사용됩니다.

class(클래스이름)
{
	//내용
}

중첩 클래스 : 클래스 내부에서 static으로 선언하며 클래스와 연관관계가 밀접한 경우에 사용합니다.

class(일반 클래스 이름)
{
	static class(중첩 클래스 이름)
    {
    	//내용
    }
}

내부 클래스 : 비 정적 중첩 클래스라고도 하며 클래스내부에 선언합니다. 이벤트를 처리하거나 데이터 구조 선언을 하기 위해 사용합니다.

class(일반 클래스 이름)
{
	class(내부 클래스 이름)
    {
    	//내용
        //static 메소드를 사용하지 않음
    }
}

지역 클래스 : 로컬 클래스라고도 하며 선언 위치는 메소드 내부입니다. 메서드 내에서만 사용되는 클래스를 생성합니다. 지역 변수를 final로 생성하는 특징이 있습니다. 지역 클래스를 포함하고 있는 메서드의 지역 변수중 지역 클래스에서 참조하는 지역 변수는 final로 선언함으로써 지역 클래스의 객체가 언제라도 참조 가능하게 합니다.

class(일반 클래스 이름)
{
	메소드
    {
    	static class(지역 클래스 이름)
        {
        	//내용
            //지역변수는 final로 선언
        }
    }
}

익명 클래스 : 선언 위치는 메소든 내부이며 단 한번만 정의하고 사용하려고 할 때 선언합니다. 지역클래스와 같으나 선언 후 ;를 붙이는 특징이 있습니다.

class(일반 클래스 이름)
{
	메소드(new class(익명 클래스 이름)
    	{
        	//내용
        }
    )
}



객체(Object)

객체는 크게 속성과 기능이라는 두 가지 구성요소로 이뤄져있습니다. 속성, 기능, 이너 클래스는 객체의 멤버(Member)라 부릅니다.



객체 생성

자동차를 예를 들어 객체로 만들어 보자면
자동차의 속성 : 모델, 바퀴 수, 문의 갯수, 색상 등
자동차의 기능 : 시동 걸기, 가속하기, 정지하기 등
이 존재 할 것입니다. 자동차를 클래스로 정의하고 인스턴스화 해보겠습니다.

class Car{
	private String model; //차 모델
    private int wheels; //바퀴 수
    private int doors; //문의 개수
    private String color; //색상
    
    void power(){} //시동 걸기
    void accelerate(){} //가속 하기
    void stop(){} //정지하기
}
public class CarTest{
	public static void main(String[] args){
    	Car bmw = new Car(); //bmw 인스턴스
        Car tesla = new Car(); //tesla 인스턴스
        Car audi = new Car(); //audi 인스턴스
    }
}

객체는 new키워드로 생성할 수 있습니다. 메서드를 활용해 객체를 전달받는 방법도 있지만, 메서드 내부에서 new를 사용 하므로 결국 동일한 방식입니다.

클래스명 참조변수명; //인스턴스(객체)를 참조하기 위한 참조변수 선언
참조
변수명 = new 생성자(매개변수); //인스턴스(객체)생성, 참조변수에 객체(인스턴스) 주소 저장
클래스명 참조_변수명 = new 생성자(매개변수); //선언과 동시에 할당

자바에서는 객체도 엄연히 개발자가 정의한 클래스라는 타입을 가집니다. 또 참조_변수는 객체의 주소를 가지며 실제로 변수에 데이터가 저장되는 것은 아닙니다.
new키워드는 객체만큼의 공간을 메모리에 할당하고 메모리상의 객체의 주소를 반환합니다.

참조_변수는 객체를 가리키고 객체내의 힙 메모리 영역에 필드, 이너클래스, 메서드(참조 주소)가 있습니다. 주의해야 할 건 메서드는 메서드 자체를 저장하는 것이 아니라 클래스 영역의 메서드에 대한 주소만 가지고 있습니다. 객체가 1~2개가 아닌 수백, 수천개, 그 이상일 때 비교적 크고 동일한 코드인 메서드가 중복되는 걸 막기 위해서 클래스 영역의 메서드를 참조하는 방식으로 주소만 저장합니다.



객체 활용

참조변수명.필드명 //필드 값
참조
변수명.메소드명(매개변수) //메서드 호출

참조_변수명.기호를 사용하여 외부에서 필드와 메서드에 접근이 가능합니다.(단, 접근지정자에 따라 불가능 할수도 있음)

이전에 만들었던 Car클래스의 필드와 메서드를 활용해 보겠습니다.

class Car{
	public String model; //필드 선언
    public String color;
    
    public Car(String model, String color){ //인스턴스 초기화를 위한 생성자 함수. 매개변수에 따라 여러종류로 선언
    	this.model = model; //this.은 필드를 가리킵니다.
        this.color = color; //this.이 없을 시 매개변수가 우선시 됩니다.
    }
    
    public Car(String model){ //매개변수가 1개인 생성자
    	this(model,"검정"); //매개변수가 2개인 생성자를 호출하면서 기본값으로 색상을 "검정"을 줍니다.
    } //this()는 객체 자신의 생성자를 호출합니다.
    
    public Car(){ //매개변수가 없는 생성자
    	this("A6"); //매개변수 1개인 생성자를 호출하면서 기본값으로 모델을 "A6"을 줍니다.
    }
    void power() { // 메서드 선언
        System.out.println("시동을 걸었습니다.");
    }
    void accelerate() {
        System.out.println("속도를 높입니다.");
    }
    void stop(){
        System.out.println("멈춥니다!");
    }
}
public class CarTest{
	public static void main(String[] args){
    	Car tesla = new Car("Model 3", "빨강"); //객체 생성. 정의한 생성자의 매개변수의 갯수, 타입에 맞춰서 인자를 넘깁니다.
       	System.out.println("내 차의 모델은 " + tesla.model + "이고 " + "색은 " + tesla.color + "입니다."); // 필드(멤버 변수) 호출
        tesla.power(); // 메서드 호출
        tesla.accelerate();
        tesla.stop();
        
        Car bmw = new Car("d520i"); //매개변수가 1개인 생성자 호출
        System.out.println("내 차의 모델은 " + bmw.model + "이고 " + "색은 " + bmw.color + "입니다."); // 필드(멤버 변수) 호출
        bmw.power();
        bmw.accelerate();
        bmw.stop();

        Car audi = new Car(); //매개변수가 없는 생성자 호출
        System.out.println("내 차의 모델은 " + audi.model + "이고 " + "색은 " + audi.color + "입니다."); // 필드(멤버 변수) 호출
        audi.power();
        audi.accelerate();
        audi.stop();
    }
}



필드

필드는 클래스에 포함된 변수를 의미하는 것으로 속성을 정의할 때 사용됩니다.

  1. 클래스 변수(class variable) : 클래스 내에서 static으로 선언되어 클래스의 인스턴스들이 공유, 클래스 정의시 생성
  2. 인스턴스 변수(instance variable) : 맴버이므로 해당 객체낸에서 공유되는 변수, new로 인스턴스 생성시 생성
  3. 지역 변수(local variable) : 메서드 안에서 선언된 변수로 메서드 안에서만 유효합니다.

변수는 선언 위치와 static키워드의 유무로 구분할 수 있습니다.

class Example{ //클래스 영역
	int instanceVariable; //인스턴스 변수
    static int classVariable; //클래스 변수(static 선언, 클래스 내 공유)
    
    void method(){ //메소드 영역
    	int localVarialbe = 0; //지역 변수, 해당 메서드안에서만 유효
    }
}



static

클래스 변수와 인스턴스 변수는 둘다 멤버이므로 static 키워드의 유무로 구분합니다. 클래스 변수와 인스턴스 변수는 역할도 다르고 생명주기(LifeLine)도 다릅니다.

클래스 변수 : 자바 실행시 생성, 객체를 만들지 않아도 접근 가능, 해당 클래스의 인스턴스들이 값을 공유 하고 객체명.멤버명 뿐 만 아니라 클래스명.멤버명으로도 접근 가능합니다.

멤버 변수 : 객체 생성시 생성, 객체를 생성한 이후에야 접근 가능, 다른 인스턴스 제각각의 값을 가짐, 객체명.멤버명으로만 접근 가능합니다.

public class StaticField{
	int num1 = 10;
    static int num2 = -10;
public class StaticFieldTest{
	public static void main(String[] args){
    	StaticField staticField1 = new StaticField();
        StaticField staticField2 = new StaticField();
        
        staticField1.num1 = 100; //인스턴스 변수 할당
        staticField2.num1 = 1000;
        
        System.out.println(staticField1.num1); //인스턴스 변수 출력
        System.out.println(staticField2.num1);

		staticField1.num2 = 150;
        staticField2.num2 = 1500;
        
        System.out.println(staticField1.num2); //클래스 변수 출력
        System.out.println(staticField2.num2);
        System.out.println(StaticField.num2);
    }
}
// 출력
100 //staticField1.num1
1000 //staticField2.num1

1500 //staticField1.num2
1500 //staticField2.num2
1500 //StaticField.num2



메서드

메서드는 특정 작업을 수행하는 명령문들의 집합입니다. Car의 power(), accelerate(), stop() 메서드들이 해당됩니다. 메서드는 다시 매서드 시그니처(method signature)메서드 바디(method body)로 구분됩니다.

자바제어자 반환타입 메서드명(매개변수){ //시그니처
	메서드 내용 //바디
}

반환 타입이 void인 경우 return이 없어도 되지만 void가 아닌 경우 반드시 return문으로 해당 데이터타입에 해당하는 데이터를 반환해야 합니다.

void printHi(){ //반환 타입이 void
	System.out.println("HI");
} //return할 필요가 없습니다.

int getNumber(){ //반환 타입이 int형
	int number = 8;
    return number; // int형 데이터를 return해야 합니다.
}



오버 로딩

메서드 오버로딩오버라이딩과 혼용하기 쉽습니다. 하지만 오버로딩은 같은 클래스내에서, 오버라이딩은 상속관계에서 메서드를 재정의 하는 것이 다릅니다.

오버로딩은 같은 역할을 하는 매서드들이 매개변수가 다르다는 이유로 여러번 중복되는걸 방지하기 위해 존재합니다. 예를 들어 계산기 메서드를 구현한다고 하면 정수를 계산할 때, 실수를 계산할 때, ascii를 계산할 때 각각 피연산자(매개변수)는 달라지지만 내부에서 동작은 동일합니다. 매개변수만 다를 경우 오버로딩을 하면 중복을 막을 수 있습니다.

public class Overloading{
	public static void main(String[] args){
    	Shape s = new Shape(); //객체 생성
        
        //매개변수에 따라 다른 메서드가 실행
        s.area(); //(1)
        s.area(5); //(2)
        s.area(10,10); //(3)
        s.area(6.0,12.0); //(4)
    }
}

class Shape{
	public void area(){ //(1)
    	System.out.println("넓이");
    }
    
    public void area(int r){ //(2)
    	System.out.println("원 넓이 = " + 3.14 * r * r);
    }
    
    public void area(int w, int l){ //(3)
    	System.out.println("직사각형 넓이 = " + w * l);
    }
    
    public void area(double b, double h){ //(4)
    	System.out.println("삼각형 넓이 = " 0.5 * b * h);
    }
}

/*
//출력

넓이
원 넓이 = 78.5
직사각형 넓이 = 100
삼각형 넓이 = 36.0
*/

메소드 오버로딩 조건

  • 메서드의 이름이 같아야 합니다.
  • 매개변수의 타입과 개수가 달라야 합니다.
  • 메서드의 반환타입은 상관 없습니다.



후기

클래스와 변수는 선언된 위치에 따라 종류가 다양해 질 수 있고 어떻게 사용되는지도 달라지므로 잘 유의해서 익혀두면 나중에라도 유용하게 쓸 수 있으니 다시 한번 보자!




GitHub

https://github.com/ds02168/CodeStates/tree/main/src/JAVA_OOP_Found

profile
오늘도 내일도 화이팅!

0개의 댓글