과목명 : 객체지향 프로그래밍(Object oriented programming)
수업일자 : 2022년 11월 02일 (수)
1. 객체 지향 프로그래밍 언어(Object Oriented Programming Language)
1-1. 객체 지향 프로그래밍(Object Oriented Programming, OOP)
- 객체 지향 프로그래밍이란, 절차 지향 프로그래밍(Procedural programming)의 방식을 보완하기 위해 등장하게 된 프로그래밍 패러다임(Programming paradigm) 중 하나로써, 프로그래밍에서 필요한 데이터들을 추상화시킨 뒤 특정한 상태와 행위를 가지는 객체를 만들고 그 객체들 간의 유기적인 상호 작용을 통해 모든 로직을 구성하도록 하는 프로그래밍 기법 중 하나입니다.
1-2. 객체 지향 언어의 역사
- 과학, 군사적 모의 실험(Simulation)을 진행하기 위해 컴퓨터를 사용하게 되면서 컴퓨터를 이용하여 가상 세계를 구현하려는 노력으로부터 객체 지향 이론이 시작되었습니다.
- 1960년대 최초의 객체 지향 언어인 "Simula"가 탄생했습니다.
- 1980년대 절차 방식 프로그래밍의 한계를 객체 지향 프로그래밍 방식으로 극복하고자 노력했으며 이를 통해 C++, Smalltalk과 같은 보다 발전된 객체 지향 프로그래밍 언어가 탄생했습니다.
- 1995년 말, Java가 개발되었으며 객체 지향 프로그래밍 언어의 주류가 되었습니다.
1-3. 객체 지향 언어의 특징
(1) 기존 프로그래밍 언어와 크게 다르지 않습니다.
- 기존 프로그래밍 언어에 몇 가지 규칙을 추가한 부분입니다.
(2) 코드의 재사용성이 높습니다.
- 새로운 코드를 작성할 때 기존의 코드를 이용해서 쉽게 작성할 수 있습니다.
(3) 코드의 관리(유지보수)가 쉽습니다.
- 코드 간의 관계를 맺어줌으로써 보다 적은 노력으로 코드 변경이 가능합니다.
(4) 신뢰성이 높은 프로그램을 개발할 수 있게 합니다.
- 제어자와 메서드를 이용해서 데이터를 보호하고, 코드의 중복을 제거하여 코드의 불일치로 인한 오류를 방지할 수 있습니다.
2. 클래스(Class)와 객체(Object)
2-1. 클래스의 정의와 용도
(1) 정의
- 클래스란, 객체를 정의할 수 있는 설계도와 같은 의미로 사용됩니다. Java에서는 객체를 생성할 수 있는 설계도인 클래스를 가지고 여러 객체를 생성하여 사용할 수 있습니다.
(2) 용도
- 클래스는 객체를 생성하는데 사용됩니다.
2-2. 객체의 정의와 용도
(1) 정의
- 클래스의 인스턴스라고도 부르며 실제 소프트웨어 세계에 구현할 대상입니다.
- 실제로 존재하는 것, 사물 또는 개념이라고도 정의됩니다.
(2) 용도
- 객체의 속성과 기능에 따라 모두 다릅니다.
2-3. 객체와 인스턴스
(1) 객체(Object)는 인스턴스(Instance)를 포함하는 일반적인 의미입니다.
(2) 인스턴스화(Instantiate) : 클래스로부터 인스턴스를 생성하는 것을 의미합니다.
2-4. 객체의 구성요소
(1) 객체는 속성과 기능으로 이루어져 있습니다.
- 객체는 속성과 기능의 집합이며, 속성과 기능을 객체의 멤버(Member, 구성요소)라고 합니다.
(2) 속성은 변수로, 기능은 메서드로 정의합니다.
- 클래스를 정의할 때 객체의 속성은 변수로, 기능은 메서드로 정의합니다.
class Car {
// 차들의 속성(변수로 정의, 차례대로 차의 이름, 색상, 문의 개수)
String carName;
String carColor;
int carDoor;
// 차들의 기능(메서드로 정의, 엔진 시동 On/Off 기능, 기어 조절 기능)
void engineOnOff() { engineOn = !engineOn; }
void gearType(int gearCount) {
int gearState = 0;
gearState = gearCount;
}
}
2-5. 인스턴스의 생성과 사용
(1) 인스턴스 생성 방법
- 문법 : 클래스명.참조변수명 = new 클래스명();
- 객체(클래스의 인스턴스)가 생성된다면 생성된 객체의 주소는 선언한 참조변수(Reference variable)에 저장됩니다.
// 객체(클래스의 인스턴스)를 생성하고, 생성된 객체의 주소를 참조변수에 저장합니다.
Car car1 = new Car(); // 생성된 Car의 객체의 주소를 참조변수 car1에 저장
(2) 인스턴스와 참조변수의 관계
- (a) 하나의 인스턴스를 여러 개의 참조변수가 가리키는 것은 가능합니다.
- (b) 여러 개의 인스턴스를 하나의 참조변수가 가리키는 것은 불가능합니다.
2-6. 클래스의 또 다른 관점 (정의 - 1)
(1) 변수 : 하나의 데이터를 저장할 수 있는 공간
(2) 배열 : 같은 데이터 타입의 여러 데이터를 저장할 수 있는 공간
(3) 구조체 - 데이터 타입에 관계없이 서로 관련있는 데이터들을 저장할 수 있는 공간
(4) 클래스 - 데이터와 메서드의 결합(구조체 + 메서드)
2-7. 클래스의 또 다른 관점 (정의 - 2)
(1) 클래스는 사용자 정의 타입(User-defined type)입니다.
- 직접 새로운 타입을 정의할 수 있으며, 서로 관련된 값이나 기능들을 묶어서 하나의 타입으로 정의합니다.
3. 변수(Variable)와 메서드(Method)
3-1. 선언 위치에 따른 변수의 종류
- 변수의 선언 위치가 변수의 종류와 범위(Scope)를 결정합니다.
class VariableType {
// 인스턴스 변수
int instanceVariable;
// 클래스 변수
static int classVariable;
void method() {
// 지역 변수
int localVariable = 0;
}
}
변수의 종류 | 선언 위치 | 생성 시기 |
클래스 변수(Class variable) | 클래스 영역 | 클래스가 메모리에 적재될 때 |
인스턴스 변수(Instance variable) | 인스턴스가 생성될 때 | |
지역 변수(Local variable) | 메서드 영역 | 변수를 선언할 때 |
(1) 인스턴스 변수(Instance variable)
- 클래스에서 정의된 변수로 이를 위해 각각 인스턴스화된 클래스의 객체들의 개별적인 저장 공간입니다.
- 각 인스턴스마다 다른 값을 저장할 수 있습니다.
- 인스턴스를 생성할 때 인스턴스 변수가 생성되고, 참조변수가 없는 경우엔 Garbage collector에 의해 자동으로 제거됩니다.
(2) 클래스 변수(Class variable)
- 동일한 클래스의 모든 인스턴스들이 공유하는 변수입니다.(모든 인스턴스가 공통된 값을 공유)
따라서, 생성된 각 객체(인스턴스)들이 공통적인 값을 가져야 할 때 클래스 변수를 선언합니다.
- 인스턴스 생성 없이, "클래스명.클래스 변수명"으로 접근 가능합니다.
- 선언 시, 데이터 타입 옆에 static 키워드를 붙입니다.
- 클래스가 로딩될 때 생성되고 프로그램이 종료될 때 소멸합니다.
(3) 지역 변수(Local Variable)
- 메서드 내에 선언되며, 메서드의 종료와 함께 소멸합니다.
- 조건문, 반복문의 블럭 내에 선언된 지역변수는 블럭을 벗어나는 순간 소멸됩니다.
3-2. 클래스 변수와 인스턴스 변수의 차이
- 인스턴스 변수는 인스턴스(객체)가 만들어질 때마다 생성되므로 만들어진 각각의 인스턴스(객체)마다 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스(객체)가 하나의 저장 공간을 공유하므로 항상 공통된 값을 가집니다.
3-3. 메서드(Method)
(1) 정의와 특징
- 특정 작업이나 연산을 수행하기 위한 명령문의 집합입니다.
- 특정 값을 파라미터로 전달받아서 작업을 처리하고 그 결과값을 리턴합니다.
- 리턴값이 없는 경우 메서드 정의 시 메서드명 옆에 void를 붙입니다.
- 메서드는 클래스 영역에서만 정의할 수 있습니다.
- 문법 : 리턴값의 데이터 타입 메서드명(데이터 타입 변수명 1, 데이터 타입 변수명 2, ... 데이터 타입 변수명 n) {
// 메서드 호출 시 수행할 문장;
}
int numberAdd(int number1, int number2) {
// 메서드 호출 시 수행문
int result = number1 + number2;
// 수행 결과값 반환
return result;
}
(2) 메서드의 장점
- 반복적인 코드를 줄이고 코드의 유지보수(관리)가 용이해집니다.
(3) 메서드의 작성 방법
- 반복적으로 수행되는 여러 문장을 메서드로 작성합니다.
- 하나의 메서드는 한 가지 기능만 수행하도록 작성합니다.
- 관련된 여러 문장을 메서드로 작성합니다.
3-4. return문
(1) 메서드가 정상적으로 종료되는 경우입니다.
- 메서드의 블록{} 끝에 도달한 경우
- 메서드의 수행문 수행 도중, return문을 만났을 때
(2) return문
- 현재 실행 중인 메서드를 종료하고 메서드를 호출한 지점으로 되돌아갑니다.
- 메서드의 반환값(리턴값)이 없는 경우 : return; 형태로 작성합니다.
- 메서드의 반환값(리턴값)이 있는 경우 : return 반환값; 형태로 작성합니다
(3) return문 작성 시 유의 사항
- 반환값이 존재하는 메서드는 모든 경우에 return문이 있어야 합니다.
int maxValue(int num1, int num2) {
if (num1 > num2) return num1;
else return num2;
}
(4) return문을 적절히 사용하면 코드가 간결해질 수 있습니다.
3-5. 메서드의 호출
(1) 메서드 호출
- 문법 : 참조변수명 또는 클래스명.메서드명();
- 문법 : 참조변수명 또는 클래스명.메서드명(전달인자 1, 전달인자 2, ... );
3-6. JVM의 대략적인 메모리 구조
(1) Method area (메서드 영역)
- 클래스 정보, 클래스 변수가 저장되는 영역입니다.
(2) 호출 스택(Call stack)
- 메서드의 작업 공간으로 메서드가 호출되면 메서드 수행에 필요한 메모리 공간을 할당받고, 메서드가 종료되면 사용한 메모리 공간을 반환하게 됩니다.
(3) Heap 영역
- 동적으로 생성된 객체(인스턴스)가 저장되는 공간이며 new 연산자에 의해 생성된 배열과 객체는 모두 여기에 생성됩니다.
3-7. JVM의 메모리 구조 - Call Stack(호출 스택)
(1) 메서드가 호출되면 수행에 필요한 메모리를 스택에 할당받습니다.
(2) 메서드가 수행을 마치면 사용했던 메모리 공간을 반환합니다.
(3) 호출 스택 맨 위에 있는 메서드가 현재 실행 중인 메서드입니다.
(4) 각 메서드의 아래에 있는 메서드가 위의 메서드를 호출한 메서드입니다.
3-8. 기본형 매개변수와 참조형 매개변수
- 기본형 매개변수 : 변수의 값을 읽을 수만 있습니다.
- 참조형 매개변수 : 변수의 값을 읽고 수정할 수 있습니다.
3-9. 재귀 호출(Recursive call)
- 재귀 호출이란, 메서드 내부에서 메서드가 자기 자신을 또 다시 호출하는 행위를 의미합니다.
- 재귀 호출은 반복문으로 바꿀 수 있으며 반복문보다 성능이 좋지 않습니다.
- 이해하기 쉽고 간결한 코드를 작성할 수 있습니다.
- 재귀 호출의 예시 : 팩토리얼, 제곱, 트리 운행,. 폴더 표시 목록 등...
// 팩토리얼 메서드의 재귀 호출
long factorialCal(int n) {
long result = 0;
if (n == 1) { result = 1; }
else { result = n * factorialCal(n-1); }
return result;
}
3-10. 클래스(Static) 메서드와 인스턴스 메서드
(1) 클래스(Static) 메서드
- 객체 생성 없이, "클래스명.메서드명();"으로 호출 가능합니다
- 인스턴스 변수나 인스턴스 메서드와는 관련 없는 작업을 수행하는 메서드입니다.
- 메서드 내부에서 인스턴스 변수를 사용할 수 없습니다.
이러한 이유 때문에 인스턴스 변수를 사용하지 않는 메서드에 Static 키워드를 붙입니다.
- 메서드 내부에서 인스턴스 변수를 사용하지 않는다면 static을 붙이는 것을 고려합니다.
(2) 인스턴스 메서드
- 객체 생성 후 "참조변수명.메서드명();"으로 호출 가능합니다.
- 인스턴스 변수나, 인스턴스 메서드와 관련된 작업을 하는 메서드입니다.
- 메서드 내부에서 인스턴스 변수를 사용할 수 있습니다.
class OOP {
long a, b;
// 인스턴스 메서드
long add(long a, long b) {
return a + b;
}
// 클래스 메서드(Static 메서드)
static long add2(long a, long b) {
return a + b;
}
public static void main(String[] args) {
// 클래스 메서드 호출
System.out.println(OOP.add2(200L, 100L)); // 300
// 클래스의 인스턴스 생성
OOP mm = new OOP();
// 생성된 객체의 인스턴스 변수에 값 할당
mm.a = 20L;
mm.b = 10L;
// 인스턴스 메서드 호출
System.out.println(mm.add(mm.a, mm.b)); // 30
}
}
3-11. 멤버 간의 참조와 호출 - 메서드의 호출
- 동일한 클래스의 멤버 간에는 객체 생성이나 참조변수 없이 참조가 가능합니다.
- 그러나 Static 계열의 멤버들은 인스턴스 멤버들을 참조할 수 없습니다.
(Static 메서드는 인스턴스 변수를 사용할 수 없음)
- 인스턴스 메서드 내부에서 인스턴스 변수를 사용하는 경우는 인스턴스 메서드 호출 행위가 객체 생성 시 가능한 경우이므로, 인스턴스 변수도 사용할 수 있습니다.
- Static 메서드는 해당 클래스에 대한 객체 생성 없이 호출이 가능하나 인스턴스 변수의 경우 객체 생성이 이루어졌는지 장담할 수 없기에, Static 메서드(클래스 메서드)에선 인스턴스 변수를 사용할 수 없습니다.
class TestClass {
// 인스턴스 변수
int instanceVariable;
// 클래스 변수
static int classVariable;
// 인스턴스 메서드
void instanceMethod() {
System.out.println(instanceVariable); // 인스턴스 변수 사용 가능
System.out.println(classVariable); // 클래스 변수 사용 가능
}
// 클래스(Static) 메서드
static void classMethod() {
// System.out.println(instanceVariable); 인스턴스 변수 사용 불가
System.out.println(classVariable); // 클래스 변수 사용 가능
}
}
- Static 메서드는 이러한 이유 때문에 인스턴스 메서드도 호출할 수 없습니다.
class TestClass {
// 인스턴스 메서드
void instanceMethod() {}
// Static(클래스) 메서드
static void classMethod {}
// 인스턴스 메서드
void instanceMethod2() {
instanceMethod(); // 다른 인스턴스 메서드를 호출 가능
classMethod(); // Static(클래스) 메서드를 호출 가능
{
// Static(클래스) 메서드
static void classMethod2() {
// instanceMethod(); 인스턴스 메서드 호출 불가
classMethod(); // Static(클래스) 메서드 호출 가능
}
}
- 학부에서 수강했던 전공 수업 내용을 정리하는 포스팅입니다.
- 내용 중에서 오타 또는 잘못된 내용이 있을 시 지적해 주시기 바랍니다.
'전공 수업 > 객체 지향 프로그래밍(Java)' 카테고리의 다른 글
[12주 차] - 클래스 상속, 메서드 오버라이딩, 참조변수 super, 생성자 super(), 패키지와 import문 (0) | 2022.11.20 |
---|---|
[11주 차] - 메서드 오버로딩, 생성자, 참조변수 this, 멤버 변수 초기화 (0) | 2022.11.10 |
[9주 차] - 메서드의 개념, 클래스와 객체 (0) | 2022.11.04 |
[7주 차] - Math.random() 메서드, 제어문(반복문, 조건문)을 사용한 코드 예제 (0) | 2022.10.12 |
[6주 차] - 배열(Array)의 선언과 생성, 초기화, 다차원 배열 (2) | 2022.10.07 |
댓글