본문 바로가기
Programming/Java프로그래밍및실습

[자프실] 4. 클래스와 객체

by Lizardee 2024. 1. 4.
4.1 객체 지향과 자바
세상 모든 것이 객체다.

 

자바의 객체 지향 특성

▶ 캡슐화(encapsulation): 객체를 캡슐로 싸서 그 내부를 보호하고 볼 수 없게 만든 것

  • 클래스(class): 객체의 모양을 선언한 틀
  • 실체(instance): 객체

 

▶ 상속(inheritance): 상위 객체의 속성이 하위 객체에 물려져서, 하위 개체가 상위 개체의 속성을 모두 가지는 관계

  • 확장(extends): 자식 클래스가 부모 클래스의 속성을 물려받아 부모 클래스에 기능을 확장하는 것
    • 슈퍼 클래스(super class): 부모 클래스
    • 서브 클래스(sub class): 자식 클래스

: 상속은 슈퍼클래스에 만들어진 필드와 메소드를 물려받음으로써 코드의 중복 작성을 방지하고, 코드를 재사용함으로써 코드 작성에 드는 시간과 비용을 줄인다.

 

▶ 다형성(polymorphism): 같은 이름의 메소드가 클래스 혹은 객체에 따라 다르게 구현되는 것

  • 메소드 오버라이딩(overriding): 슈퍼클래스에서 구현된 메소드를 서브클래스에서 자신의 특징에 맞게 동일한 이름으로 다시 구현하는 것
  • 메소드 오버로딩(overloading): 클래스 내에서 같은 이름의 메소드를 여러 개 만드는 것

 

객체 지향 언어의 목적
  • 소프트웨어의 생산성 향상
  • 실세계에 대한 쉬운 모델링

 

절차 지향 프로그래밍 & 객체 지향 프로그래밍
  • 절차 지향 프로그래밍: C언어처럼 실행하고자 하는 절차를 정하고, 이 절차대로 프로그래밍하는 방법
  • 객체 지향 프로그래밍: 실세상의 물체를 객체로 표현하고, 이들 사이의 관계, 상호작용을 프로그램으로 나타내는 방법
    --> 객체를 추출하고, 객체들의 관계를 결정하고, 이들의 상호작용에 필요한 함수(메소드)와 변수(필드)를 설계 및 구현한다.

 

클래스와 객체
  • 클래스: 객체를 만들어내기 위한 설계(틀)
  • 인스턴스(instance): 클래스에 선언된 모양 그대로 생성된 실체 (= 객체)

 


4.2 자바 클래스 만들기
자바 클래스 구성

자바 클래스 구성

  • 클래스 멤버
    • 필드(field): 객체의 상태 값을 저장할 멤버 변수
    • 메소드(method): 실행 가능한 함수
  • 접근 지정자: 클래스에 대한 접근 권한 설정

 

객체 생성과 활용
// 예제 4-1
// 반지름과 이름을 가진 Circle 클래스를 작성하고, Circle 클래스의 객체를 생성하라.

public class Circle {
	int r;  // 원의 반지름 필드
	String name;  // 원의 이름 필드
	
	public double getArea() {  // 멤버 메소드
		return 3.14*r*r;
	}
	
	public static void main(String[] args) {
		// 피자
		Circle pizza = new Circle();  // 객체에 대한 레퍼런스 변수 pizza
		pizza.r = 10;
		pizza.name = "자바피자";
		
		double area = pizza.getArea();
		System.out.println(pizza.name + "의 면적은 " + area);
		
		// 도넛
		Circle donut = new Circle();
		donut.r = 3;
		donut.name = "자바도넛";
		
		area = donut.getArea();
		System.out.println(donut.name + "의 면적은 " + area);
	}
}

 

// 예제 4-2
// 너비와 높이를 입력받아 사각형의 면적을 출력하는 프로그램

import java.util.Scanner;

class Rectangle{
	int w;
	int h;
	
	public int getArea() {
		return w*h;
	}
}

public class RectangleApp {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		
		Rectangle rect = new Rectangle();
		System.out.print(">>");
		rect.w = scanner.nextInt();
		rect.h = scanner.nextInt();
		
		System.out.println("사각형의 면적은 " + rect.getArea());
		
		scanner.close();
	}
}

 


4.3 생성자
생성자의 개념과 목적
  • 생성자: 객체가 생성될 때 초기화를 위해 실행되는 메소드

 

생성자 작성 및 활용
// 예제 4-3
// 두 개의 생성자를 가진 Circle_ 클래스

public class Circle_ {
	int radius;
	String name;
	
	// 생성자 이름 = 클래스 이름
	public Circle_() {  // 매개변수가 없는 생성자
		radius = 3;  // r의 초기값은 1
		name = " ";
	}
	
	public Circle_(int r, String n) {  // 매개변수를 가진 생성자
		radius = r;
		name = n;
	}
	
	public double getArea() {
		return 3.14*radius*radius;
	}
	
	public static void main(String[] args) {
		Circle_ pizza = new Circle_(10, "자바피자");
		double area = pizza.getArea();
		System.out.println(pizza.name + "의 면적은 " + area);
		
		Circle_ donut = new Circle_();
		donut.name = "자바도넛";
		area = donut.getArea();
		System.out.println(donut.name + "의 면적은 " + area);
	}
}

 

// 예제 4-4
// title과 author 필드를 가진 Book 클래스를 작성하고, 생성자를 작성하여 필드를 초기화하라.

public class Book {
	String title;
	String author;
	
	// 생성자1
	public Book(String t) {
		title = t;
		author = "작자미상";
	}
	
	// 생성자2
	public Book(String t, String a) {
		title = t;
		author = a;
	}
	
	public static void main(String[] args) {
		Book littlePrince = new Book("어린왕자", "생텍쥐페리");
		
		Book loveStory = new Book("춘향전");
		
		System.out.println(littlePrince.title +", " + littlePrince.author);
		System.out.println(loveStory.title + ", " + loveStory.author);
	}
}

 

기본 생성자(dafault constructor)
  • 기본 생성자(default constructor): 매개변수가 없고, 실행코드가 없어서 아무 일도 하지 않고 단순 리턴하는 생성자

 

this 레퍼런스
  • this: 객체 자신에 대한 레퍼런스

 

this()로 다른 생성자 호출
// 예제 4-5
// this()로 다른 생성자 호출

public class Book_ {
	String title;
	String author;
	
	void show() {
		System.out.println(title + ", " + author);
	}
	
	public Book_() {
		this(" ", " ");
		System.out.println("생성자 호출됨");
	}
	
	public Book_(String title) {
		this(title, "작자미상");
	}
	
	public Book_(String title, String author) {
		this.title = title;
		this.author = author;
	}
	
	public static void main(String[] args) {
		Book_ littlePrince = new Book_("어린왕자", "생텍쥐페리");
		Book_ loveStory = new Book_("춘향전");
		Book_ emptyBook = new Book_();
		
		loveStory.show();
	}
}

 


4.4 객체 배열
객체 배열
  • 객체 배열: 객체에 대한 레퍼런스를 원소로 갖는 배열

 

객체 배열 선언 및 생성

객체 배열 선언 및 생성

 

배열의 원소 객체 접근

객체 배열의 선언과 생성

// 예제 4-6
// 반지름이 0~4인 Circle 객체 5개를 가지는 배열을 생성하고, 배열에 있는 모든 Circle 객체 면적을 출력하라.

class Circle{
	int radius;
	
	public Circle(int radius) {
		this.radius = radius;
	}
	
	public double getArea() {
		return 3.14*radius*radius;
	}
}

public class CircleArray {
	public static void main(String[] args) {
		Circle[] c = new Circle[5];  // Circle 배열에 대한 레퍼런스 배열
		
		for(int i=0; i<c.length; i++)
			c[i] = new Circle(i);  // i번째 원소 객체 
		
		for(int i=0; i<c.length; i++)
			System.out.print((int)(c[i].getArea()) + " ");
	}
}

 

// 예제 4-7
// 2개짜리 객체 배열을 만들고, 사용자로부터 책의 제목과 저자를 입력받아 배열을 완성하라.

import java.util.Scanner;

class Book{
	String title;
	String author;
	
	public Book(String title, String author) {
		this.title = title;
		this.author = author;
	}
}

public class BookArray {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		
		Book[] mybook = new Book[2];
		
		for(int i=0; i<mybook.length; i++) {
			System.out.print("제목>>");
			String title = scanner.nextLine();
			
			System.out.print("저자>>");
			String author = scanner.nextLine();
			
			mybook[i] = new Book(title, author);  // 배열 원소 객체 생성
		}
		
		for(int i=0; i<mybook.length; i++)
			System.out.print("(" + mybook[i].title + ", " + mybook[i].author + ") ");
		
		scanner.close();
	}
}

 


4.5 메소드 활용과 객체 치환
메소드 형식

메소드 형식

▶ 접근 지정자

: 자바에서 메소드는 반드시 접근 지정자와 함께 선언되어야 한다.

  • public: 클래스 내부/외부에서 모두 호출 가능
  • private: 클래스 멤버들만 호출 가능
  • protected: 동일한 패키지의 클래스들, 상속받은 서브 클래스에서 호출 가능
  • 디폴트 접근 지정: 동일한 패키지 내의 모든 클래스에서 호출 가능

 

▶ 리턴 타입

: 메소드가 호출자에게 리턴할 값의 타입

 

인자 전달
  • 메소드 호출 시 인자 전달 방식(argument passing) - 값에 의한 호출(call-by-value)
    : 호출하는 값이 복사되어 메소드의 매개 변수에 전달된다.

1) 기본 타입의 값이 전달되는 경우

 

2) 객체가 전달되는 경우

 

3) 배열이 전달되는 경우

 

// 예제 4-8
// char[] 배열을 전달받아 배열 속의 공백(' ') 문자를 ','로 대치하는 메소드

public class ArrayPassing {
	static void replaceSpace(char a[]) {
		for(int i=0; i<a.length; i++)
			if(a[i] == ' ')
				a[i] = ',';
	}
	
	static void printCharArray(char a[]) {
		for(int i=0; i<a.length; i++)
			System.out.print(a[i]);
		System.out.println();
	}
	
	public static void main(String[] args) {
		char c[] = {'L', 'e', 'e', ' ', 'J', 'i', 'W', 'o', 'n'};
		printCharArray(c);
		replaceSpace(c);
		printCharArray(c);
	}
}

 

 

메소드 오버로딩

: 클래스 내에 이름이 같지만 매개 변수의 타입이나 개수가 서로 다른 여러 개의 메소드를 작성하는 것

성공한 오버로딩과 메소드 호출
오버로딩 실패 사례

 

객체 치환 시 주의할 점
  • 객체의 치환은 객체를 복사하는 것이 아니며, 레퍼런스의 복사이다.

 


4.6 객체의 소멸과 가비지 컬렉션
객체의 소멸

: new에 의해 할당 받은 객체와 배열 메모리를 자바 가상 기계로 되돌려 주는 행위

 

가비지

: 가리키는 레퍼런스가 하나도 없는 객체 --> 더 이상 접근할 수 없어 사용될 수 없게 된 메모리

예제4-9: 가비지의 발생

 

가비지 컬렉션(garbage collection)

: 자바 가상 기계가 가비지 자동 회수

 

가비지 컬렉션 강제 수행

: System 또는 Runtime 객체의 gc() 메소드 호출

System.gc();  // 가비지 컬렉션 작동 요청

 


4.7 접근 지정자
자바의 패키지 개념
  • 패키지: 상호 관련 있는 클래스 파일(컴파일된 .class)을 저장하여 관리하는 디렉터리

 

접근 지정자(access specifier)

: 클래스나 멤버들을 다른 클래스에서 접근해도 되는지의 여부를 선언하는 지시어

  • private, protected, public, 디폴트(접근지정자 생략)

접근 지정자에 따른 클래스나 멤버의 공개 범위

 

클래스 접근 지정

: 다른 클래스에서 사용하도록 허용할 지 지정

  • public 클래스: 패키지에 상관없이 다른 어떤 클래스에게도 사용이 허용됨
  • 디폴트 클래스(접근 지정자 생략): 같은 패키지 내에 있는 클래스들에게만 사용이 허용됨

클래스 접근 지정

 

멤버 접근 지정

멤버 접근 지정

  • public 멤버: 패키지를 막론하고 모든 클래스들이 접근 가능함
  • private 멤버: 비공개 - 클래스 내의 멤버들에게만 접근 허용됨
  • protected 멤버: 보호된 공개 - 패키지 내의 모든 클래스에서 접근 가능함, 다른 패키지에 있더라도 자식 클래스의 경우 접근 허용됨
  • 디폴트 멤버: 동일한 패키지에 있는 클래스 내의 멤버들에게만 접근 허용됨

 


4.8 static 멤버
static 멤버 선언

static 멤버 선언

 

static 멤버의 특성
  • static 멤버는 클래스당 하나만 생성됨
  • 객체들에 의해 공유됨

static 멤버의 특성

 

static 멤버 사용

static 멤버 사용

 

static의 활용
  • 전역변수, 전역함수
  • 공유 멤버
// 예제 4-11
// 전역함수로 작성하고자 하는 abs, max, min의 3개 함수를 static 메소드를 작성하고 호출하는 사례

class Calc{
	public static int abs(int a) {
		return (a>0)?a:-a;
	}
	public static int max(int a, int b) {
		return (a>b)?a:b;
	}
	public static int min(int a, int b) {
		return (a>b)?b:a;
	}
}

public class CalcEx {
	public static void main(String[] args) {
		System.out.println(Calc.abs(-5));
		System.out.println(Calc.max(10,8));
		System.out.println(Calc.min(-3, 8));
	}
}

 

static 메소드의 제약 조건
  • static 메소드는 오직 static 멤버만 접근 가능하다.
  • static 메소드에서는 this를 사용할 수 없다.

 


4.9 final
final 클래스

: final이 클래스 이름 앞에 사용되면, 클래스를 상속받을 수 없음을 지정한다.

 

final 메소드

: 메소드 앞에 final이 붙으면, 이 메소드는 더 이상 오버라이딩할 수 없음을 지정한다.

 

final 필드

: 자바에서 final로 필드를 선언하면, 필드는 상수가 된다.