클래스 - 1

Bummy·2023년 7월 13일
0

JAVA

목록 보기
5/11
post-thumbnail

6.1 객체 지향 프로그래밍

  • 부품에 해당되는 객체들을 먼저 만들고, 그 객체들을 하나씩 조립해서 완성된 프로그래밍을 만드는 기법을 객체 지향 프로그래밍(OOP : Object Oriented Programming)이라고 한다.

6.1.1 객체란?

  • 객체란 물리적으로 존재하거나 추상적으로 생각할 수 있는 것 중에서 자신의 속성을 가지고 있는 것을 의미
  • 객체는 속성과 동작으로 구성되어 있고 자바에서는 이 속성과 동작을 각각 필드(field)와 메소드(method)라고 부른다.
  • 현실 세계의 객체를 소프트웨어 객체로 설계하는 것을 객체 모델링이라고 한다.

6.1.2 객체의 상호작용

  • 객체들을 각각 독립적으로 존재하고 다른 객체와 서로 상호작용하면서 동작한다.
  • 이 상호작용 수단이 메소드이며, 객체가 다른 객체의 기능을 이용하는 것이 메소드 호출이다.
리턴값 = 전자계산기객체.메소드(매개값1, 매개값2);

6.1.3 객체 간의 관계

  • 객체간의 관계에는 집합 관계, 사용 관계, 상속 관계가 있다.

집합 관계

  • 하나는 부품이고 하나는 완성품에 해당한다.

사용 관계

  • 객체 간의 상호작용을 의미
  • 객체는 다른 객체의 메소드를 호출하여 원하는 결과를 얻어낼 수 있다.

상속 관계

  • 상위(부모) 객체를 기반으로 하위(자식) 객체를 생성하는 관계

6.1.4 객체 지향 프로그래밍 특징

캡슐화

  • 객체의 필드, 메소드를 하나로 묶고 실제 구현 내용을 감추는 것을 의미
  • 외부 객체는 객체 내부의 구조를 알지 못하며 객체가 노출해서 제공하는 필드와 메소드만 이용할 수 있다.
  • 캡슐화된 멤버를 노출시킬 것인지, 숨길 것인지를 결정하기 위해 접근 제한자(Access Modifier)를 사용한다.

상속

  • 상위 객체를 재사용해서 객체를 쉽고 빨리 설계할 수 있다.
  • 반복된 코드의 재사용을 줄일 수 있다.
  • 상속은 상위 개체의 수정으로 모든 하위 객체들의 수정 효과를 가져오므로 유지 보수 시간을 최소화할 수 있다.

다형성

  • 하나의 타입에 여러 객체를 대입함으로써 다양한 기능을 이용할 수 있도록 해준다.

6.2 객체와 클래스

  • 객체 지향 프로그래밍에서 클래스(class)는 설계도로 설명할 수 있고 클래스로부터 만들어진 객체를 해당 클래스의 인스턴스(instance)라고 한다.
  • 하나의 클래스로부터 여러 개의 인스턴스를 만들 수 있다.

6.3 클래스 선언

  • 클래스 이름은 작성 규칙에 맞춰 선언해야하며 한글이든 영어든 상관없지만, 한글로 클래스 이름을 만드는 경우는 거의 없다.
public class Car{

}
  • 다음과 같이 Car 클래스를 선언 후 소스 파일을 컴파일하면 소스 파일은 “Car.java”로 생성되게 된다.
public class Car{

}

class Tire{

}
  • 다음과 같이 두 개 이상의 클래스를 선언할 수 있다.
  • 두 개 이상의 클래스가 선언된 소스 파일을 컴파일하면 바이트 코드 파일은(.class) 클래스를 선언한 개수만큼 생성되게 된다.
  • 파일 이름과 동일한 이름의 클래스 선언에만 public 접근 제한자를 붙일 수 있으며 파일 이름과 일치하지 않는 클래스 선언에 public 접근 제한자를 붙이면 컴파일 에러가 발생한다.

6.4 객체 생성과 클래스 변수

  • 클래스로부터 객체를 생성하는 방법은 new 연산자를 사용하면 된다.
클래스 변수 = new 클래스();
  • new 연산자는 힙 영역에 객체를 생성시킨 후, 객체 주소를 리턴하도록 되어 있다. 이 주소를 참조 타입인 클래스 변수에 저장해 두면 변수를 통해 객체를 사용할 수 있게 된다.
  • 클래스 변수를 참조 변수라고도 부를 수 있다.

클래스 용도

  • 클래스에는 라이브러리(API : Application Program Interface)용이고 다른 하나는 실행용이다.
  • 라이브러리 클래스는 다른 클래스에서 이용할 목적으로 설계된다.
  • 실행 클래스는 프로그램의 실행 진입점인 main() 메소드를 제공하는 역할을 한다.

6.5 클래스의 구성 멤버

  • 클래스의 구성 멤버에는 필드(Field), 생성자(Constructor), 메소드(Method)가 있다.
  • 이 구성 멤버들은 생략되거나 복수 개가 작성될 수 있다.
public class ClassName{
	//필드 : 객체와 데이터가 저장되는 곳
	int fieldName;

	//생성자 : 객체 생성 시 초기화 역할 담당
	ClassName() {
	};

	//메소드 : 객체의 동작에 해당하는 실행 블록
	void methodName(){
	};

}

6.5.1 필드

  • 객체의 고유의 데이터, 부품 객체, 상태 정보를 저장하는 곳
  • 변수와 비슷하지만 변수는 생성자와 메소드 내에서만 사용되고 생성자와 메소드가 실행 종료되면 자동 소멸된다.
  • 필드는 생성자와 메소드 전체에서 사용되며 객체가 소멸되지 않는 한 객체와 함께 존재한다.

6.5.2 생성자

  • 생성자는 new 연산자로 호출되는 특별한 중괄호 블록이다.
  • 객체 생성 시 초기화를 담당하며 필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 한다.
  • 생성자는 메소드와 비슷하게 생겼지만, 클래스 이름으로 되어 있고 리턴 타입이 없다.

6.5.3 메소드

  • 객체 간의 데이터 전달 수단으로 사용되며 외부로부터 매개값을 받을 수도 있고, 실행 후 어떤 값을 리턴할 수도 있다.

6.6 필드

  • 필드는 객체의 고유 데이터, 객체가 가져야 할 부품, 객체의 현재 상태 데이터를 저장하는 곳

6.6.1 필드 선언

  • 필드 선언은 클래스 중괄호 {} 블록 어디서든 존재할 수 있다.
  • 생성자와 메소드 중괄호 블록 내부에는 선언될 수 없다,
💡 생성자와 메소드 중괄호 블록 내부에 선언된 것 = 로컬 변수 필드 = 클래스 멤버 변수
  • 타입에는 기본 타입(byte, short, int, long, float, double, boolean)과 참조 타입(배열, 클래스, 인터페이스)가 모두 올 수 있다.
  • 필드의 초기값은 필드 선언 시 주어질 수도 있고, 생략될 수도 있다.

→ 필드 선언 예

String company = "현대자동차";
String model = "그랜저";
int maxSpeed = 300;
int productionYear;
int currentSpeed;
boolean engineStart;

6.6.2 필드 사용

  • 클래스 내부의 생성자나 메소드에서 사용할 경우 단순하게 필드 이름으로 읽고 변경하면 된다.
  • 클래스 외부에서 사용할 경우 우선적으로 클래스로부터 객체를 생성한 뒤 필드를 사용해야한다.
  • 필드는 객체에 소속된 데이터이므로 객체가 존재하지 않으면 필드도 존재하지 않는다.

→ 필드 사용 예

Car myCar = new Car();
myCar.speed = 60;

6.7 생성자

  • 생성자(Constructor)는 new 연산자와 같이 사용되어 클래스로부터 객체를 생성할 때 호출되어 객체의 초기화를 담당한다.
  • 생성자를 실행시키지 않고는 클래스로부터 객체를 만들 수 없다.
  • 생성자가 성공적으로 실행되지 않고 예외(에러)가 발생했다면 객체는 생성되지 않는다.

6.7.1 기본 생성자

  • 모든 클래스는 생성자가 반드시 존재하며, 하나 이상을 가질 수 있다.
  • 클래스 내부에 생성자 선언을 생략했다면 컴파일러는 기본 생성자(Default Constructor)를 바이트 코드에 자동 추가시킨다.
  • 클래스에 명시적으로 선언한 생성자가 한 개라도 있으면, 컴파일러는 기본 생성자를 추가하지 않는다.

6.7.2 생성자 선언

클래스(매개변수 선언, ...){
	//객체의 초기화 코드
}
  • 메소드와 비슷한 모양을 가지고 있으나, 리턴 타입이 없고 클래스 이름과 동일하다
  • 매개 변수 선언은 생략할 수도 있고, 여러 개를 선언할 수도 있다.
Car myCar = new Car("그랜저", "검정", 300);

public class Car{
//생성자
	Car(String model, String color, int maxSpeed){
		...
	}
}
  • 세 매개값을 생성자가 받기 위해서는 다음과 같이 생성자를 선언해야한다.
  • 생성자가 명시적으로 선언되어 있을 경우 반드시 생성자를 호출해서 객체를 생성해야만 한다.

6.7.3 필드 초기화

  • 필드를 초기화하는 방법은 두가지 방법이 있는데 하나는 필드를 선언할 때 초기값을 주는 방법이고, 또 다른 하나는 생성장에서 초긱밧을 주는 방법이다.
  • 객체 생성 시점에 다양한 값을 가져야한다면 생성자의 매개값으로 이 값을 받아 초기화하는 것이 맞다.
public class Korean{
	//필드
	String nation = "대한민국";
	String name;
	String ssn;

	//생성자
	public Korean(String n, String s){
		name = n;
		ssn = s;
	}
}

→ 사용 예

	Korean k1 = new Korean("박자바", "011225-1234567");
	Korean k2 = new Korean("김자바", "930525-0654321");
  • 관례적으로 필드와 동일한 이름을 갖는 매개 변수를 사용해야한다.
  • 필드와 매개 변수 이름이 동일하기 때문에 생성자 내부에서 해당 필드에 접근할 수 없는데, 그 이유는 동일한 이름의 매개 변수가 사용 우선순위가 높기 때문이다.
  • 이럴 때 “this.”를 붙여 사용하면 된다.

→ 사용 예

public Korean(String name, String ssn){
	this.name = name;    //this.필드 = 매개변수;
	this.ssn = ssn;      //this.필드 = 매개변수;

6.7.4 생성자 오버로딩(Overloading)

  • 다양한 방법으로 객체를 생성할 수 있도록 생성자 오버로딩을 제공한다.
  • 매개 변수를 달리하는 생성자를 여러 개 선언하는 것을 의미한다.
  • 매개 변수의 타입, 개수, 순서를 달리하여 선언하면 된다.

6.7.5 다른 생성자 호출(this())

  • 생성자 오버로딩이 많아질 경우 생성자 간의 중복된 코드가 발생할 수 있다.
  • 필드 초기화 내용을 한 생성자에만 집중적으로 작성하고 나머지 생성자는 초기화 내용을 가지고 있는 생성자를 호출하는 방법으로 개선할 수 있다.
public class Car{
	//필드
	String company = "현대자동차';
	String model;
	String color;
	int maxSpeed;
	
	//생성자
	Car(){
	}

	Car(String model){
		this(model, "은색", 250);
	}

	Car(String model, String color){
		this(model, color, 250);
	}
	
	Car(String model, String color, int maxSpeed){
		this.model = model;
		this.color = color;
		this.maxSpeed = maxSpeed; //공통 실행 코드
	}
}

6.8 메소드

  • 객체의 동작에 해당하는 중괄호 블록을 의미
  • 필드를 읽고 수정하는 역할도 하지만, 다른 객체를 생성해서 다양한 기능을 수행하기도 한다.

6.8.1 메소드 선언

  • 메소드 선언은 선언부(리턴타입, 메소드 이름, 매개변수선언)와 실행 블록으로 구성된다.
  • 메소드 선언부를 메소드 시그니처라고도 한다.

리턴 타입

  • 메소드가 실행 후 결과를 호출한 곳에 넘겨줄 경우에는 리턴값이 있어야 한다.
  • 리턴 값이 없는 메소드는 void가 와야하며 리턴값이 있는 메소드는 리턴값의 타입이 와야한다.

메소드 이름

  • 메소드 이름은 자바 식별자 규칙에 맞게 작성하면 된다.

숫자로 시작하면 안되고, $와 _를 제외한 특수 문자를 사용하지 말아야 한다.
관례적으로 메소드명은 소문자로 작성한다.
서로 다른 단어가 혼합된 이름이라면 뒤이어 오는 단어의 첫머리 글자는 대문자로 작성한다.

매개 변수 선언

  • 메소드가 실행할 때 필요한 데이터를 외부로부터 받기 위해 사용된다.
double divide(int x, int y){
	//실행부
}

double result = divide(10, 20);

매개 변수의 수를 모를 경우

  • 메소드를 선언할 때 매개 변수의 개수를 알 수 없는 경우 매개 변수를 배열 타입으로 선언하면 된다.
int sum1(int[] values){
//실행부
}

//ex)
int[] values = {1, 2, 3};
int result = sum1(values);
int result = sum1(new int[] {1, 2, 3, 4, 5});
  • 매개 변수를 배열 타입으로 선언하면, 메소드를 호출하기 전에 배열을 만들어줘야하는 불편한 점이 있다.
int sum2(int ... values){
//실행부
}

int result = sum2(1, 2, 3);
int result = sum2(1, 2, 3, 4, 5);
  • 다음과 같이 “…”를 사용해서 선언하게 되면, 메소드 호출 시 넘겨준 값의 수에 따라 자동으로 배열이 생성되고 매개값으로 사용된다.

6.8.2 리턴(return)문

리턴값이 있는 메소드

  • 리턴 타입이 있는 메소드는 반드시 리턴문을 사용해서 리턴값을 지정해줘야한다.
  • return문이 없다면 컴파일 오류가 발생하게 된다.
  • return문이 실행되면 메소드는 즉시 종료된다.

6.8.3 메소드 호출

  • 클래스 내부의 다른 메소드에서 호출할 경우는 단순한 메소드 이름으로 호출하면 된다.
  • 클래스 외부에서 호출할 경우에는 우선 클래스로부터 객체를 생성한 뒤, 참조 변수를 이용해서 메소드를 호출해야한다. 객체가 존재해야 메소드가 존재하기 때문이다.

객체 내부에서 호출

메소드(매개값, ...);

객체 외부에서 호출

  • 외부 클래스에서 메소드를 호출하려면 클래스로부터 객체를 생성해야한다.
클래스 참조변수 = new 클래스(매개값, ...);
  • 객체가 생성되었다면 참조 변수와 함께 도트(.) 연산자를 사용해서 메소드를 호출할 수 있다.
  • 도트(.) 연산자는 객체 접근 연산자로 객체가 가지고 있는 필드나, 메소드에 접근할 때 사용된다.
참조변수.메소드(매개값, ...); //리턴값이 없거나, 있어도 리턴값을 받지 않을 경우
타입 변수 = 참조변수.메소드(매개값, ...); //리턴값이 있고, 리턴값을 받고 싶을 경우

6.8.4 메소드 오버로딩

  • 클래스 내에 같은 이름의 메소드를 여러 개 선언하는 것을 의미
  • 조건은 매개 변수의 타입, 개수, 순서 중 하나가 달라야한다.
int plus(int x, int y){
	int result = x + y;
	return result;
}

double plus(double x, double y){
	double result = x + y;
	return result;
}
  • 오버로딩된 메소드를 호출할 경우 JVM은 매개값의 타입을 보고 메소드를 선택한다.
💡 메소드 호출 시 매개 변수의 타입이 다를 경우 컴파일 오류가 날 것 같지만, 자바는 자동 타입 변환이 가능한지 검사하기에 자동 타입 변환이 가능하다면 컴파일 오류가 발생하지 않는다.

0개의 댓글