Study Web Development

11월 5일

이전으로

자바

6. 클래스와 객체

  1. 새 패키지 kr.s06.animal 생성하고 새 클래스 Animal 생성
package kr.s06.animal;

public class Animal {
	// 멤버 변수
	private String name; // 이름
	private int age; // 나이
	private boolean fly; // 비행 여부

	// Getters and Setters
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public boolean isFly() { // boolean형은 데이터를 읽어올 때 get이 아닌 is를 사용하는 것이 표준
		return fly;
	}
	public void setFly(boolean fly) {
		this.fly = fly;
	}

	// 인자를 받는 생성자
	public Animal(String name, int age, boolean fly) {
		this.name = name;
		this.age = age;
		this.fly = fly;
	}

	// 인자 없는 기본 생성자; 명시하지 않을 경우 기본 생성자 사용 불가
	public Animal() {}
}
  1. 새 클래스 AnimalMain 생성
package kr.s06.animal;

public class AnimalMain {
	public static void main(String[] args) {
		// 기본 생성자를 이용하여 객체 생성
		Animal a1 = new Animal();

		// 기본 정보 세팅
		a1.setName("기린");
		a1.setAge(10);
		a1.setFly(false);

		// 정보 출력
		System.out.println("이름 : " + a1.getName());
		System.out.println("나이 : " + a1.getAge());
		System.out.println("비행 여부 : " + (a1.isFly() ? "가능" : "불가능")); // 삼항 연산자를 이용해서 true일 때 가능, false일 때 불가능 출력; 우선순위 문제가 있으니 소괄호 필요
		
		System.out.println();
		
		// 생성자로 기본 정보 세팅
		Animal a2 = new Animal("기러기", 3, true);

		// 정보 출력
		System.out.println("이름 : " + a2.getName());
		System.out.println("나이 : " + a2.getAge());
		System.out.println("비행 여부 : " + printFly(a2.isFly())); // 같은 클래스의 static 메서드는 클래스명 명시하지 않고 호출 가능
	}

	// 삼항 연산자 이용하는 메서드 만들기; 메서드 위치는 main 위, 아래 무관
	private static String printFly(boolean fly) { // 객체 생성 없이 호출 가능
		return fly ? "가능" : "불가능";
	}
}

5. 배열

  1. 새 패키지 kr.s07.array 생성하고 새 클래스 Book 생성
package kr.s07.array;

public class Book {
	// 멤버 변수
	private String category; // 분류
	private String name; // 도서명
	private int price; // 가격
	private double discount; // 할인율

	// Getters and Setters
	public String getCategory() {
		return category;
	}
	public void setCategory(String category) {
		this.category = category;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public double getDiscount() {
		return discount;
	}
	public void setDiscount(double discount) {
		this.discount = discount;
	}

	// 배열에 넣는 것을 편리하게 하기 위해 생성자 명시
	public Book() {}
	public Book(String category, String name, int price, double discount) {
		this.category = category;
		this.name = name;
		this.price = price;
		this.discount = discount;
	}
}
  1. 새 클래스 BookMain 생성
package kr.s07.array;

public class BookMain {
	public static void main(String[] args) {
		// Book 객체를 요소로 갖는 배열 선언 및 생성
		Book[] bookArray = new Book[3]; // 길이 3인 배열이 생성되고, 각 요소는 null로 초기화됨; 객체가 아직 생성되지 않아 주소가 없다는 의미
		int total = 0;
		
		// Book 객체를 3개 생성하여 배열에 저장
		bookArray[0] = new Book("IT", "Java", 5000, 0.05); // 생성된 객체의 주소가 배열의 0번 인덱스에 저장됨
		bookArray[1] = new Book("미술", "고흐", 4000, 0.03);
		bookArray[2] = new Book("음악", "아리랑", 6000, 0.06);
		
		// 배열의 요소 출력; 참조값이 출력됨
		System.out.println(bookArray[0]);
		System.out.println(bookArray[1]);
		System.out.println(bookArray[2]);
		
		// 반복문을 이용해 배열에 접근해서 객체를 호출하고 객체의 멤버 변수에 저장된 데이터 출력
		for(int i=0;i<bookArray.length;i++) {
			System.out.print(bookArray[i].getCategory() + "\t"); // 객체의 멤버 변수는 private이라 직접 접근 불가
			System.out.print(bookArray[i].getName() + "\t");
			System.out.printf("%,d원\t", bookArray[i].getPrice());
			System.out.printf("%.2f%%\n", bookArray[i].getDiscount()); // printf에서 %를 일반 문자로 출력하려면 %% 사용
		}
		
		System.out.println();
		
		// 확장 for문
		for(Book book : bookArray) { // 참조 자료형은 클래스명 Book을 적고 참조 변수 book을 선언
			System.out.printf("%s\t", book.getCategory());
			System.out.printf("%s\t", book.getName());
			System.out.printf("%,d원\t", book.getPrice());
			System.out.printf("%.2f%%\n", book.getDiscount());
			total += book.getPrice(); // 합계
		}

		// 합계 출력
		System.out.printf("가격의 합 : %,d원", total);
	}
}
  1. 새 클래스 Score 생성
package kr.s07.array;

public class Score { // 클래스명을 대문자로 시작해야 변수명과 헷갈리지 않음
	/*
	 * [실습]
	 * 멤버 변수 이름(name), 국어(korean), 영어(english), 수학(math) 생성
	 * 반환형이 int인 총점을 구하는 메서드(makeSum), 평균을 구하는 메서드(makeAvg) 생성
	 * 반환형이 String인 등급을 구하는 메서드(makeGrade) 생성
	 * 인자가 없는 생성자, 인자가 있는 생성자 명시
	 */
	// 은닉화
	private String name;
	private int korean;
	private int english;
	private int math;

	// Getters and Setters
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getKorean() {
		return korean;
	}
	public void setKorean(int korean) {
		this.korean = korean;
	}
	public int getEnglish() {
		return english;
	}
	public void setEnglish(int english) {
		this.english = english;
	}
	public int getMath() {
		return math;
	}
	public void setMath(int math) {
		this.math = math;
	}

	// 총점, 평균, 등급을 구하는 메서드
	public int makeSum() { // 메서드는 동작을 의미하므로 메서드명은 동사형을 사용
		return korean+english+math;
	}
	public int makeAvg() {
		return makeSum()/3;
	}
	public String makeGrade() {
		String grade;
		switch(makeAvg()/10) {
		case 10:
		case 9:
			grade = "A"; break;
		case 8:
			grade = "B"; break;
		case 7:
			grade = "C"; break;
		case 6:
			grade = "D"; break;
		default:
			grade = "F";
		}
		return grade;
	}

	// 생성자
	Score(){}
	Score(String name, int korean, int english, int math){
		this.name=name;
		this.korean=korean;
		this.english=english;
		this.math=math;
	}
}
  1. 새 클래스 ScoreMain 생성
package kr.s07.array;

public class ScoreMain {
	public static void main(String[] args) {
		/*
		 * [실습]
		 * 배열 생성, 배열의 길이 4
		 * 자료형이 int인 반 전체의 총점(total), 반 전체의 평균(avg) 변수 생성
		 * Score 객체를 4개 생성해서 배열에 저장
		 * 반복문을 이용하여 배열에 접근해서 객체의 데이터를 읽기
		 * 반 전체의 총점과 평균 출력
		 */
		Score[] scoreArray=new Score[4];

		int total=0;
		int avg=0 ;
		/* 입력을 받아 객체를 생성
		java.util.Scanner input = new java.util.Scanner(System.in);
		for(int i=0;i<scoreArray.length;i++) {
			System.out.print("이름 > ");
			String name = input.nextLine();
			System.out.print("국어 > ");
			int korean = input.nextInt();
			System.out.print("영어 > ");
			int english = input.nextInt();
			System.out.print("수학 > ");
			int math = input.nextInt();
			input.nextLine(); // 수학 점수를 입력하면서 친 엔터(\n)를 흡수하는 용도; 없을 경우 루프를 돌 때 이름이 \n으로 입력됨
			scoreArray[i] = new Score(name, korean, english, math);
		}
		input.close();
		*/
		scoreArray[0]=new Score("홍길동", 98, 96, 88);
		scoreArray[1]=new Score("이순신", 99, 72, 82);
		scoreArray[2]=new Score("장영실", 97, 83, 81);
		scoreArray[3]=new Score("김유신", 86, 66, 83);
		
		for(Score score : scoreArray) {
			System.out.print(score.getName()+"\t");
			System.out.print(score.getKorean()+"\t");
			System.out.print(score.getEnglish()+"\t");
			System.out.print(score.getMath()+"\t");
			System.out.print(score.makeSum()+"\t");
			System.out.print(score.makeAvg()+"\t");
			System.out.print(score.makeGrade()+"\n");
			total += score.makeSum();
		}
		avg = total / (scoreArray.length * 3);
		System.out.println("반 전체의 총점 : "+total+"\t반 전체의 평균 : "+avg);
	}
}

7. 객체의 활용

7-1 상속

  1. 새 자바 프로젝트 ch06-object2 생성하고 새 패키지 kr.s01.extension 생성 후 새 클래스 ExtensionMain01 생성
package kr.s01.extension;
// 부모 클래스
class Parent extends Object { // 기본적으로 생략되며, 자바의 모든 클래스는 자동적으로 Object가 상속됨
	int a = 100;
}

// 자식 클래스
class Child extends Parent {

}

public class ExtensionMain01 {
	public static void main(String[] args) {
		Child ch = new Child();
		System.out.println(ch.a); // 상속 관계를 맺으면 부모 클래스의 자원을 자식 클래스에서 가져다 쓸 수 있음
	}
}
  1. 새 클래스 ExtensionMain02 생성
package kr.s01.extension;
// 부모 클래스
class People {
	public void eat() {
		System.out.println("식사하다.");
	}
}

// 자식 클래스
class Student extends People {
	public void study() {
		System.out.println("공부하다.");
	}
}

public class ExtensionMain02 {
	public static void main(String[] args) {
		Student s = new Student();
		s.eat(); // People의 메서드를 상속받아 호출
		s.study(); // Student의 메서드를 호출
		System.out.println(s.toString()); // Object의 메서드를 (People을 통해) 상속받아 호출
		System.out.println(s); // 참조 변수만 쓸 경우 자동적으로 toString()을 호출
	}
}
  1. 새 클래스 ExtensionMain03 생성
package kr.s01.extension;
// 부모 클래스
class A {
	int x = 100; // 접근 제한자를 생략시 default로 설정되며, 같은 패키지 내에서 호출 가능
	private int y = 200; // 같은 클래스 내에서만 호출 가능하도록 은닉화
	
	public int getY() {
		return y;
	}
}

// 자식 클래스
class B extends A {
	int z = 300;
}

public class ExtensionMain03 {
	public static void main(String[] args) {
		B bp = new B();
		System.out.println(bp.x);
		// System.out.println(bp.y); // private 멤버 변수는 상속 관계를 맺어도 같은 클래스가 아니기 때문에 호출 불가
		System.out.println(bp.getY()); // 부모 클래스에서 public 메서드를 만들어두면 은닉화된 y의 값을 복사해서 전달받을 수 있음
		System.out.println(bp.z);
	}
}
  1. 새 패키지 kr.s02.packonekr.s02.packtwo 생성 후 kr.s02.packone에 새 클래스 People 생성
package kr.s02.packone;

public class People {
	// 같은 클래스에서만 호출 가능
	private int a = 10;
	// 같은 패키지에서만 호출 가능
	int b = 20;
	// 같은 패키지이거나 상속 관계이면 호출 가능
	protected int c = 30;
	// 접근 제한이 없음
	public int d = 40;
}
  1. kr.s02.packtwo에 새 클래스 AccessMain 생성
package kr.s02.packtwo;

import kr.s02.packone.People; // import하지 않으면 패키지가 달라 People 클래스를 생성할 수 없음

public class AccessMain {
	public static void main(String[] args) {
		People p = new People();
		// System.out.println(p.a); // private; 같은 클래스가 아니기 때문에 호출 불가
		// System.out.println(p.b); // default; 같은 패키지가 아니기 때문에 호출 불가
		// System.out.println(p.c); // protected; 같은 패키지도 아니고 상속 관계도 아니기 때문에 호출 불가
		System.out.println(p.d); // public; 접근 제한이 없으므로 호출 가능
	}
}
  1. 새 클래스 AccessMain02 생성
package kr.s02.packtwo;

import kr.s02.packone.People; // import하지 않으면 패키지가 달라 People 클래스를 상속받을 수 없음

class Student extends People {
	public void print() {
		// System.out.println("a = " + a); // private; 상속 관계라도 같은 클래스가 아니므로 호출 불가
		// System.out.println("b = " + b); // default; 상속 관계라도 같은 패키지가 아니므로 호출 불가
		System.out.println("c = " + c); // protected; 상속 관계이므로 다른 패키지라도 호출 가능
		System.out.println("d = " + d); // public; 접근 제한이 없으므로 호출 가능
	}
}

public class AccessMain02 {
	public static void main(String[] args) {
		Student s = new Student();
		s.print();
	}
}
상속의 중요성
  1. 새 패키지 kr.s03.extension 생성하고 새 클래스 Phone 생성
package kr.s03.extension;

public class Phone {
	// 패키지가 달라질 것을 염두에 두고 접근 제한자를 지정
	protected String number;
	protected String model;
	protected String color;

	// Getters; Setters를 만들지 않고 생성자로 기능 대체
	public String getNumber() {
		return number;
	}
	public String getModel() {
		return model;
	}
	public String getColor() {
		return color;
	}
}
  1. 새 클래스 SmartPhone 생성
package kr.s03.extension;

public class SmartPhone extends Phone {
	private String os;

	public String getOs() {
		return os;
	}

	// SmartPhone 객체를 생성하면 메모리에 먼저 Object 영역이 만들어지고(=Object 클래스의 멤버가 메모리에 올라감), 다음으로 부모 클래스 영역이 만들어지며(=부모 클래스의 멤버가 메모리에 올라감), 마지막으로 자식 클래스 영역이 생성됨(=자식 클래스의 멤버가 메모리에 올라감); 세 영역은 별도의 객체가 아니라 하나의 객체(=하나의 주소)
	public SmartPhone(String number, String model, String color, String os) {
		this.number = number; // Phone의 number를 상속받았기 때문에 자신(=this)의 것처럼 인식
		this.model = model;
		this.color = color;
		this.os = os;
	}
}
  1. 새 클래스 FeaturePhone 생성
package kr.s03.extension;

public class FeaturePhone extends Phone {
	private int pixel; // 사진의 화소 수; 자바에서 일반적으로 멤버 변수의 접근 제한자는 public을 제외하고 사용하며, 지역 변수는 해당 변수가 정의된 메서드의 접근 제한자를 따라감
	
	public int getPixel() {
		return pixel;
	}
	
	public FeaturePhone(String number, String model, String color, int pixel) {
		this.number = number;
		this.model = model;
		this.color = color;
		this.pixel = pixel;
	}
}
  1. 새 클래스 PhoneMain 생성
package kr.s03.extension;

public class PhoneMain {
	public static void main(String[] args) {
		SmartPhone sp = new SmartPhone("010-1234", "A1001", "White", "Android");
		FeaturePhone fp = new FeaturePhone("010-4321", "Z1001", "Black", 800);
		
		System.out.println("번호\t모델\t색상\t옵션(OS/화소 수)");
		
		System.out.print(sp.getNumber() + "\t");
		System.out.print(sp.getModel() + "\t");
		System.out.print(sp.getColor() + "\t");
		System.out.print(sp.getOs() + "\n");
		
		System.out.print(fp.getNumber() + "\t");
		System.out.print(fp.getModel() + "\t");
		System.out.print(fp.getColor() + "\t");
		System.out.print(fp.getPixel() + "\n");
	}
}

7-2 메서드 오버라이딩

  1. 새 패키지 kr.s04.overriding 생성하고 새 클래스 OverridingMain01 생성
package kr.s04.overriding;
// 부모 클래스
class GrandParent {
	public String getCar() {
		return "구형 자동차";
	}
}

// 자식 클래스
class Father extends GrandParent {
	// 메서드 오버라이딩; 메서드의 형식은 같고 내용만 교체
	@Override
	public String getCar() {
		return "신형 자동차";
	}
}

// 자식 클래스
class Uncle extends GrandParent {
	
}

public class OverridingMain01 {
	public static void main(String[] args) {
		Father ft = new Father();
		System.out.println(ft.getCar()); // GrandParent에서 상속받은 메서드 대신 Father에서 재정의한 메서드가 호출됨
		
		Uncle uc = new Uncle();
		System.out.println(uc.getCar()); // GrandParent에서 상속받은 메서드가 호출됨
	}
}
  1. 새 클래스 OverridingMain02 생성
package kr.s04.overriding;
// 부모 클래스
class Dad {
	public String getLunch() {
		return "밥";
	}
}

// 자식 클래스
class Son extends Dad {
	
}

// 자식 클래스
class Daughter extends Dad {
	@Override
	public String getLunch() {
		return "빵";
	}
}

public class OverridingMain02 {
	public static void main(String[] args) {
		Son s = new Son();
		System.out.println("아들은 " + s.getLunch() + "을 먹는다.");
		
		Daughter d = new Daughter();
		System.out.println("딸은 " + d.getLunch() + "을 먹는다.");
	}
}
  1. 새 클래스 OverridingMain03 생성
package kr.s04.overriding;

class People {
	
}

class Animal {
	// Object의 메서드를 오버라이딩
	@Override public String toString() {
		return "Animal";
	}
}

public class OverridingMain03 {
	public static void main(String[] args) {
		People p = new People();
		System.out.println(p.toString()); // Object의 toString()
		
		Animal a = new Animal();
		System.out.println(a.toString()); // Object의 toString()을 재정의
		System.out.println(a);
	}
}

다음으로