Java/정석

객체 지향

hs_developer 2022. 5. 24. 17:06

p242-249 정리

 

객체 배열

많은 수의 객체를 배열로 다루면 편리하다. 이를 객체 배열이라 한다. 그렇다고 객체 배열 안에 객체가 저장되는 것은 아니고, 객체의 주소가 저장된다. 객체 배열은 참조 변수들을 하나로 묶은 참조 변수 배열인 것이다.

 

TV tv1, tv2, tv3

TV[] tvArr = new TV[3];

 

 

길이가 3인 객체 배열 tvArr을 위와 같이 생성하면 각 요소는 참조 변수의 기본 값인 null로 자동 초기화 된다. 그리고 이 객체 배열은 3개의 객체 주소를 저장한다.

 

객체 배열을 생성하는 건, 그저 객체를 다루기 위한 참조 변수들이 만들어진 것일 뿐, 아직 객체가 생성되지 않았다. 객체를 생성해서 객체 배열의 각 요소에 저장해야 한다. 객체 배열만 생성해서 에러가 발생하는 게 흔하다.

 

 

TV[] tvArr = new TV[3]; // 참조 변수 배열 생성

// 객체를 생성해서 배열의 각 요소에 저장
tvArr[0] = new TV();
tvArr[1] = new TV();
tvArr[2] = new TV();

 

배열의 초기화 블럭을 사용하면, 다음과 같이 한 줄로 간단히 할 수 있다.

TV[] tvArr = {new TV(), new TV(), new TV()};

 

다뤄야할 객체 수가 많을 때는 for문 사용한다. (**)

TV[] tvArr = new TV[100];

for(int i=0; i<tvArr.length; i++)
{
	tvArr[i] = new TV;
}

 

 

모든 배열이 그렇 듯이 객체 배열도 같은 타입의 객체만 저장할 수 있다. 그럼, 여러 종류의 객체를 하나의 배열에 저장할 수 있는 방법은 없을까? '다형성'으로 하나의 배열로 여러 종류의 객체를 다룰 수 있다.

 

 

tvArr[0].channel = 11
tvArr[1].channel = 12
tvArr[2].channel = 13
class TV
{
    String color;
    boolean power;
    int channel;

    void power() 
    {
    	power = !power;
    }

    void channelUp() 
    {
    	++channel;
    }

    void channelDown() 
    {
    	--channel;
    }
}


public class test {

	public static void main(String[] args) {
		
		TV[] tvArr = new TV[3]; // 길이가 3인 TV 객체 배열
		
		// TV 객체 생성해서 TV 객체 배열의 각 요소에 저장
		for(int i=0; i<tvArr.length; i++)
		{
			tvArr[i] = new TV();
			tvArr[i].channel = i+10;
		}
		
		for(int i=0; i<tvArr.length; i++)
		{
			tvArr[i].channelUp();
			System.out.printf("tvArr[%d].channel = %d%n", i, tvArr[i].channel);
		}
	}
}

 

 


 

클래스

 

하나의 데이터를 저장하기 위해 변수를, 같은 종류의 데이터를 효율적으로 다루기 위해 배열을 사용하며, 후에는 구조체로 자료형의 종류에 상관 없이 서로 관련 있는 변수들을 하나로 묶어 관리한다.

 

그 동안 데이터는 데이터끼리, 함수는 함수끼리 따로 다루었지만, 사실 함수는 주로 데이터를 가지고 작업하기 때문에 객체지향은 변수와 함수를 함께 다룰 수 있게 한다.

 

 

int[] hour = new int[3];
int[] minute = new int[3];
float[] second = new float[3];

class Time
{
    int hour;
    int minute;
    float second;
}

 

비객체향적 코드 객체지향적 코드
int hour1, hour2, hour3;
int minute1, minute2, minute3;
float second1, second2, second3;
Time t1 = new Time();
Time t2 = new Time();
Time t3 = new Time();
int[] hour = new int[3];
int[] minute = new int[3];
float[] second = new float[3];
Time[] t = new Time[3];
t[0] = new Time();
t[1] = new Time();
t[2] = new Time();

 

 


 

변수와 메소드

1. 선언 위치에 따른 변수의 종류

 

변수는 클래스 변수, 인스턴스 변수, 지역 변수 3개가 있다.

 

멤버 변수를 제외한 나머지 변수들은 모두 지역변수이며,

멤버 변수 중 static이 붙은 것은 클래스 변수,

붙지 않은 것은 인스턴스 변수이다.

 

 

class Variables
{
    int iv; // instance
    static int cv; // static

    void method()
    {
    	int lv=0; // 지역
    }
}

 

iv와 cv는 클래스 영역에 선언되어 있으므로 멤버 변수

cv는 키워드 static과 함께 선언되어 있으므로 static 변수이며, iv는 인스턴스 변수

lv는 method() 내부인 메소드 영역에 선언되어 있으므로 지역 변수

 

 

 

 

2. 클래스 변수와 인스턴스 변수

 

카드 클래스를 작성하기 위해서는 카드를 분석해 속성과 기능을 알아내야 한다. 카드 무늬, 숫자, 폭, 높이 정도가 있다. 이 중에서 어떤 속성을 클래스 변수로, 어떤 속성을 인스턴스 변수로 선언할 지 생각한다.

 

class Card
{
    String kind; // 무늬
    int number; // 숫자

    static int width = 100; // 폭
    static int height = 250; // 높이
}

 

각 Card 인스턴스는 자신만의 무늬와 숫자를 유지하고 있어야 하므로 인스턴스 변수이고,

각 카드의 폭과 높이는 모든 인스턴스가 공통적으로 값을 유지해야 하므로 클래스 변수이다. 

 

 

 

Card.width = 100
Card.height = 250

c1은 Heart, 7이며, 크기는 100, 250입니다.
c2은 Spade, 4이며, 크기는 100, 250입니다.

// static이라서 c1, c2 모두 변경
c1의 width와 height를 각각 50, 80으로 변경합니다.
c1은 Heart, 7이며, 크기는 50, 80입니다.
c2은 Spade, 4이며, 크기는 50, 80입니다.
class Card
{
	String kind;
	int number;
	static int width = 100;
	static int height = 250;
}


public class test {

	public static void main(String[] args) {
		
		System.out.println("Card.width = " + Card.width);
		System.out.println("Card.height = " + Card.height);
		
		Card c1 = new Card();
		c1.kind = "Heart";
		c1.number = 7;
		
		Card c2 = new Card();
		c2.kind = "Spade";
		c2.number = 4;
		
		System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 " + c1.width + ", " + c1.height + "입니다.");
		
		System.out.println("c2은 " + c2.kind + ", " + c2.number + "이며, 크기는 " + c2.width + ", " + c2.height + "입니다.");
		
		System.out.println("c1의 width와 height를 각각 50, 80으로 변경합니다.");
		
		// static이라서 c2 값도 변경 됨
		c1.width = 50;
		c1.height = 80;
		
		System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 " + c1.width + ", " + c1.height + "입니다.");
		
		System.out.println("c2은 " + c2.kind + ", " + c2.number + "이며, 크기는 " + c2.width + ", " + c2.height + "입니다.");
		
	}
}

 

Card 인스턴스인 c1과 c2는 클래스 변수인 width와 height를 공유하기 때문에, c1의 width와 height를 변경하면 c2의 width와 height도 같은 결과를 얻는다.