[JAVA 기초부터 훑어보기 PART2]07. 클래스와 객체

2023. 1. 18. 23:57JAVA(자바)

1. 객체 지향이란

(1) 정의 

- 객체 지향 프로그래밍(object-oriented programming: OOP)은 실제 세계가 객체들로 구성되어 있는 것과 비슷하게 소프트웨어도 객체 단위로 작성하는 방법

- 객체들은 나름대로 고유한 기능을 수행하면서 다른 객체들과 상호 작용한다

실제 세계는 객체로 이루어진다

 

(2) 절차 지향 프로그래밍과 객체 지향 프로그래밍

◈ 절차 지향 프로그래밍

- 1970년대에 절차 지향 프로그래밍 방법이 많이 사용되었다

- 문제를 해결하는 절차를 중요하게 생각하는 방법

- 절차들은 모두 함수(또는 프로시저)라는 단위로 묶이게 된다

- 가장 중요한 단점은 데이터가 함수와 분리된다는 점!

- 과도한 전역 변수가 사용되고 프로그램의 이해가 어려워지며 차후에 변경하거나 확장하기 어려워진다

 

◈ 객체 지향 프로그래밍

- 데이터와 절차를 하나의 덩어리(객체)로 묶어서 생각하는 방법

- 객체 지향은 현실 세계를 시뮬레이션하는 언어였던 1960년대의 시뮬라라는 언어에 기반을 두고 있다

 

 

2. 객체 지향 프로그래밍의 특징

ㄱ. 캡슐화

(1) 정의

- 관련된 데이터와 알고리즘(코드)이 하나의 묶음으로 정리되어 있는 것

- 데이터와 알고리즘을 캡슐에 넣어서 포장한다는 의미

- 데이터를 감추고 외부 세계와의 상호작용은 메소드를 통하는 방법

 

※ 정보 은닉

- 내부의 데이터를 캡슐로 보호하는 역할도 하는데 이것을 정보 은닉이라고 한다

- 정보은닉을 하는 이유는 이들 부분이 프로그램의 다른 부분에 영향을 미치지 않고 쉽게 변경될 수 있기 때문 

 

ㄴ. 상속

(1) 정의

- 기존의 코드를 재활용하기 위한 기법(이미 작성된 클래스를 이어받아 새로운 클래스를 생성하는 기법)

- 자식 클래스는 부모 클래스의 모든 속성과 동작을 물려받는다

 

◈ 오버로딩(Overloading) : 같은 이름의 메소드 여러개를 가지면서 매개변수의 유형과 개수가 다르도록 하는 것

오버라이딩(Overriding) : 상위 클래스가 가지고 있는 메소드를 하위 클래스가 재정의해서 사용

 

ㄷ. 다형성

(1) 정의

- 객체가 취하는 동작이 상황에 따라서 달라지는 것

- 다형성을 사용하게 되면 실제 동작은 다르더라도 개념적으로 동일한 작업을 하는 멤버 함수들에 똑같은 이름을 부여할 수 있으므로 코드가 더 간단해진다

 

(2) 형태

- speak()라는 멤버 함수는 모든 객체 타입마다 정의되어 있어서 호출하면 객체가 소리를 발생한다

- 객체의 소리를 발생하는 것이 필요하면 객체 타입에 관계없이 speak() 멤버 함수를 호출하면 됨! 

 

3. 객체

(1) 정의 

- 객체는 객체 지향 기술의 핵심 개념

- 객체는 상태와 동작을 가지고 있다

 

(2) 객체의 특징

- 객체의 상태와 동작은 소프트웨어에서는 각각 필드와 메소드로 표현할 수 있다

- 객체 안의 변수필드라고 하고 객체 안의 함수메소드라고 부른다 

- 객체는 필드와 메소드로 이루어져 있는 소프트웨어의 묶음이라고 할 수 있다 

- 필드객체의 상태를 저장, 메소드특정한 동작(작업)을 수행한다 

자동차 객체의 예

 

4. 메시지

(1) 정의 

- 객체는 메시지를 통해 다른 객체와 통신하고 서로 상호작용한다

- 메시지 전달은 실제로 "메소드 호출"로 구현된다 

 

(2) 예

- 운전사 객체가 자동차 객체를 가속하기를 원한다면 운전사 객체는 가속 메시지를 작성하여 자동차 객체에 전달한다.

 

(3) 형태

메시지의 구성 요소

 

 

5. 클래스

(1) 정의 

- 같은 종류의 객체들은 모두 하나의 설계도로 만들어지는데, 이 설계도를 클래스라고 한다

- 클래스로부터 만들어진 각각의 객체를 그 클래스의 인스턴스라고 한다. 

- 객체 지향 환경에서의 소프트웨어 기본 단위

 

(2) 클래스의 선언과 객체 생성

클래스의 구조

 

//저장할 때 따로 Car.java와 CarTest.java로 나눠서 저장하여도 된다
package Abstraction;

class Car{
	//필드 정의: 객체의 속성을 나타낸다
	String color;
	int speed;
	int gear;
	//메소드 정의: 객체의 동작을 나타낸다
	void print() {	
		System.out.println("{" + color + ", " + speed + ", " + gear + ")");
	}
}
public class CarTest {
	public static void main(String[] args) {
		Car myCar = new Car();	//Car 객체 생성 myCar는 Car의 인스턴스(객체)의 이름이 된다 
		myCar.color = "red";	//필드에 접근하려면 도트 연산자(.)를 사용한다
		myCar.speed = 0;
		myCar.gear = 1;
		myCar.print();
	}
}

package Abstraction;

class Car2{
	//필드 정의: 객체의 속성을 나타낸다
	String color;
	int speed;
	int gear;
	//메소드 정의: 객체의 동작을 나타낸다
	void print() {	
		System.out.println("{" + color + ", " + speed + ", " + gear + ")");
	}
}
public class CarTest2 {
	public static void main(String[] args) {
		Car myCar = new Car();
		myCar.color = "red";
		myCar.speed = 0;
		myCar.gear = 1;
		myCar.print();
		
		Car yourCar = new Car();
		yourCar.color = "blue";
		yourCar.speed = 60;
		yourCar.gear = 3;
		yourCar.print();
	}

}

 

※ 참고사항

- main() 메소드는 Car 클래스 안에 들어갈 수 있다. 하지만 그렇게 되면 Car 클래스 안에서 Car 객체가 생성되기 때문에 초보자의 경우, 이해하기가 더 힘들다. 

 

 

(3) 변수의 종류 

- 자바에서 변수를 분류하면 기초 변수참조 변수로 나눌 수 있다

기초 변수와 참조 변수

㉮ 기초 변수 

- int, float, char 등의 기초 자료형을 가지는 변수이다

- 기초 변수에는 실제 데이터 값이 저장된다

 

㉯ 참조 변수

- 객체를 참조할 때 사용되는 변수

- 객체의 주소가 들어있어서 객체가 있는 곳을 가리킨다

 

 

(4) 객체의 생성

㉮ 참조 변수 선언

- Car 타입의 객체를 참조할 수 있는 변수 myCar를 선언한다

 

㉯ 객체 생성

- new 연산자를 이용하여 객체를 생성하고 객체 참조값을 반환한다

 

㉰ 참조 변수와 객체의 연결
- 생성된 새로운 객체의 참조값을 myCar라는 참조 변수에 대입한다

 

 

(5) 객체의 필드와 메소드 접근

- 객체 내의 필드는 메소드를 통해서 간접적으로 접근하는 것이 바람직하다

- 객체에 포함된 메소드를 참조 변수를 사용하여 호출하는 경우

 

 

 

6. 메소드

(1) 정의 

- 메소드는 입력을 받아서 어떤 처리를 하고 처리의 결과를 반환하는 작은 기계와 같다

- 메소드는 다른 언어의 함수나 프로시저와 비슷하다

 

(2) 메소드의 선언 형식

public int add(int x, int y){  //접근 제어 지정자: public, private와 같은 접근 제어를 나타낸다
         return x + y; //메소드의 몸체로서 합을 계산한다, 메소드가 값을 반환할 때 return 사용
}

 

(3) 인수와 매개변수

- 메소드를 호출할 때 외부에서 메소드로 매개변수를 통하여 값을 전달할 수 있다

- 호출하는 곳에서 메소드 호출 시 전달하는 값을 인수(argument)라고 하고 메소드에서 값을 받을 때 사용하는 변수를 매개 변수(parameter)라고 한다

- int setSpeed(int s) {...}에서 s가 매개변수이다

- 메소드가 호출될 때 인수는 매개변수

- 매개변수와 인수는 서로 타입이 일치하여야 한다 

- 만약 메소드가 매개변수를 가지지 않으면 void로 표시한다

 

 

7. 객체의 일생

(1) 객체와 참조변수

- 객체는 무조건 new 연산자를 사용하여 생성된다 

- 참조 변수 사이의 대입 연산은 기초 변수와는 상당히 다름

보기1

 

보기2

 

※ 보기 2에서 yourCar는 어떤 객체를 가리키는가?

- myCar가 가지고 있던 참조값이 yourCar로 복사되기 때문에 yourCar도 동일한 객체를 가리키게 된다

 

yourCar.speed = 120;
//실행결과
System.out.println(myCar.speed);      //120 출력
System.out.println(yourCar.speed);     //120 출력

 

 

(2) 객체의 소멸

- 객체는 생성되어서 사용하다가 결국 소멸 단계를 거쳐 객체가 점유하고 있었던 기억 공간이 반환된다

- 객체가 소멸된다는 것은 객체에 할당되어 있었던 메모리를 회수한다는 뜻이다 

 

◈ 쓰레기 수집(Garbage Collection)

- 자바의 실행 환경이 사용이 끝난 객체를 스스로 판별(객체를 가리키는 참조 변수가 하나도 남아있지 않다면)하여 소멸시키고 그 객체가 가지고 있던 자원을 시스템에 반납시킨다 

Car car1 = new Car();    //첫 번째 객체
Car car2 = new Car();    //두 번쨰 객체

 

 

8. 문자열 객체의 생성과 사용

- 자바에서는 문자열도 객체로 취급된다 

 

(1) 문자열은 객체

- 문자열은 자바에서 기초 자료형이 아님(자바는 문자열을 저장할 수 있는 기초 자료형이 없음)

- String 클래스를 이용하여 문자열을 저장하고 처리할 수 있다

 

(2) 객체의 생성

- 자바에서 객체를 생성하는 방법은 단 하나, new 키워드를 사용하면 된다 

String s = new String("Hello World!");      //선언과 동시에 초기화
s = "Hello World!";    //이렇게 하여도 객체가 생성된다

 

(3) 객체의 메소드 호출

- 객체가 생성된 후에 객체의 메소드를 사용하려면 도트 연산자를 사용한다.

- String 클래스는 length()라는 이름의 메소드를 가지고 있다 length()는 문자열의 길이를 계산하여 반환한다 

- 생성된 객체를 통해 length() 메소드를 사용하려면 다음과 같이 참조 변수 뒤에 도트 연산자를 붙이고, 호출하는 메소드 이름을 적어주면 된다

String s = new String("Hello World!");
int size = s.length();          //size는 12이다 

 

 

(4) 참조 변수끼리의 대입 연산

- 참조 변수는 객체의 주소를 저장하고 있기 때문에 참조 변수끼리의 대입 연산은 기초 변수와는 다르다 

s2 = s1;

- 위의 문장을 실행하면 s1에 들어있는 값이 s2로 복사된다 

- 하지만 s1에 들어있던 값은 주소이기 때문에 s2에도 s1이 가지고 있던 주소값이 들어가게 된다 

- 처음에는 s1과 s2가 서로 다른 객체를 가리키고 있었지만 대입 연산으로 인해 같은 객체를 가리키게 된 것이다 

 

 

(5) String 클래스 

 

(6) 메소드 사용의 예 

package Method;

public class StringTest {
	public static void main(String[] args) {
		String proverb = "A barking dog";
		String s1, s2, s3, s4;
		
		System.out.println("문자열의 길이 = " + proverb.length());
		
		s1 = proverb.concat(" never Bites!");
		s2 = proverb.replace('A', 'a');
		s3 = proverb.substring(2, 5);
		s4 = proverb.toUpperCase();
		
		System.out.println(s1);
		System.out.println(s2);
		System.out.println(s3);
		System.out.println(s4);
	}

}

 

실행결과

 

 

(7) 문자열 상수

- 문자열 상수는 "Hello World!"와 같이 이중 따옴표를 사용하여 표현된다 

System.out.println("Hello World!");

- 문자열 상수도 String 클래스의 객체로 저장된다

- 따라서 String 클래스의 메소드를 문자열 상수를 통해서도 사용할 수 있다

int size = "Hello World!".length();         //문자열의 크기
System.out.println(size);                     //12가 출력된다

 

 

(8) 문자열의 결합

- 두개의 문자열은 +연산자를 이용하여 결합될 수 있다. 

- + 연산자가 문자열에 적용되는 경우, 결합 연산자라고도 부른다 

String subject = "Money";
String other = "has no valuew if it is not used";
String sentence = subject + other;           //"Money has no value if it is not used"

 

(9) 수치값을 문자열로 변환하는 방법

- 자바에서는 문자열과 기초 자료형 변수를 결합하게 되면 자동적으로 기초 자료형을 문자열로 변환한다. 따라서 아래 문장에서는 자동적으로 변수 x값이 문자열로 변환된다 

int x = 20;
System.out.println("결과 값은 " + x);       //"결과값은 20"이 출력된다

- 상수와 문자열을 결합하여도 마찬가지이다

String answer = "The answer is " + 100;       //"The answer is 100"

- 주의할 점은 수치값이 문자열에 +연산자로 합해지는 경우에만 문자열로 변환되어서 결합된다 

 

 

(10) 문자열을 수치값으로 변환하는 방법

- 기초 자료형을 객체로 포장한다 -> 랩퍼 클래스

기초 자료형 랩퍼 클래스
byte Byte
short Short
int Integer
long  Long
float Float
double Double
char Character
boolean Boolean
void void

 

- 랩퍼 클래스는 여러 가지 유용한 메소드도 제공한다

반환값 메소드 이름 설명
byte byteValue() int 형을 byte형으로 변환한다
double doubleValue() int형을 double형으로 변환한다
float floatValue() int형을 float형으로 변환한다
int parseInt(String s) 문자열을 int형으로 변환한다
String toBinaryString(int i) int형의 정수를 2진수 형태의 문자열로 변환한다
String  toBinaryString(int i) int형의 정수를 16진수 형태의 문자열로 변환한다
String toHexString(int i) int형의 정수를 8진수 형태의 문자열로 변환한다