Super Coding Addict
Ch05. 클래스와 객체(2) 본문
< 생성자, 생성자 오버로딩 >
* 생성자
- 객체를 생성할 때 new 키워드와 함께 호출
- 인스턴스를 초기화 하는 코드가 구현됨 (주로 멤버변수 초기화)
- 반환값 없음 cf. 메서드
- 상속되지 않음
- 클래스 이름과 항상 동일
* 기본생성자 : 매개 변수X, 구현부 X
- 하나의 클래스에는 반드시 하나 이상의 생성자 존재
- 프로그래머가 생성자 구현하지 않으면, 컴파일러가 생성자 코드를 넣어줌 ==> 기본 생성자
* 생성자 오버로딩
- 여러 생성자들 매개변수를 달리해서 만들 수 있음
cf. private : 이 클래스 내부에서만 쓰는 변수로 외부에서 참조할 수 없다 --> 생성자로 초기화 가능
< 참조 자료형 >
* 참조자료형
- 클래스형으로 변수를 선언 ex) String name;
- 기본자료형은 사용하는 메모리가 정해져 있지만, 참조 자료형은 클래스에 따라 다르다
- 예제 (Student와 Subject)
[ Student클래스 ]
package reference;
public class Student {
int studentID;
String studentName;
Subject korea; //참조변수 타입으로 변수 선언
Subject math; //객체생성을 해야 쓸 수 있음!
public Student(int id, String name) {
studentID = id;
studentName = name;
korea = new Subject(); //생성자에서 초기화
math = new Subject();
}
public void setKoreaSubject(String name, int score) {
korea.subjectName = name;
korea.score = score;
}
public void setMathSubject(String name, int score) {
math.subjectName = name;
math.score = score;
}
public void showStudentScore() {
int total = korea.score + math.score;
System.out.println(studentName + " 학생의 총점은 " + total + "점 입니다");
}
}
[ Subject 클래스 ]
package reference;
public class Subject {
public String subjectName;
public int score;
public int subjectID;
}
[ StudentTest클래스 (메인메서드가 있는 곳) ]
package reference;
public class StudentTest {
public static void main(String[] args) {
Student studentLee = new Student(100, "Lee");
studentLee.setKoreaSubject("국어", 100);
studentLee.setMathSubject("수학", 95);
Student studentKim = new Student(101, "Kim");
studentKim.setKoreaSubject("국어", 80);
studentKim.setMathSubject("수학", 99);
studentLee.showStudentScore();
studentKim.showStudentScore();
}
}
/* 결과
Lee 학생의 총점은 195점 입니다
Kim 학생의 총점은 179점 입니다
*/
< 정보 은닉 >
* 접근 제어자
- public, private, protected, default
: public - 모두 접근 허용
: private - 클래스 내부에서만 접근 허용
: protected - 같은 클래스 or 상위클래스가 가진 private 변수나 메서드를 하위클래스에 public하게 오픈하고 싶을 때 사용
: default(아무것도 안쓰는 경우) - 같은 패키지 내에서만 접근 허용
- private을 사용하면 클래스 외부에서는 접근 불가
* 정보 은닉
- 외부에서 클래스 내부 정보에 접근하지 못하게 함
- private 키워드 활용
- private 변수를 외부에서 접근하게 하려면 public 메서드 제공 (ex- getter, setter)
- 클래스 내부 데이터를 잘못 사용하는 오류 방지
- 예제 : 멤버변수인 month, day, year 변수를 private으로 설정하고 setter로 값 설정 / getter로 값 가져오기 ( [source] - [Generate Getters and Setters] )
--> 그러나 여전히 setter로도 유효하지 않은 값을 넣을 수 있는 것 아닌가? --> 유효성 검사를 위한 멤버변수 isValid 선언하고 false일 때 유효하지 않은 값이라고 출력
[ MyDate클래스 ]
package hiding;
public class MyDate {
private int day; //default는 같은 패키지내에서만 접근가능
private int month;
private int year;
private boolean isValid; //boolean은 멤버변수일 때 무조건 기본값은 false
public void setDay(int day) {
this.day = day; //멤버변수 이름과 매개변수 이름이 같을 때 this로 구분하기
}
public int getDay() {
return day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
if ( month < 1 || month > 12) {
isValid = false;
}
else
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public void showDate() {
if(isValid) {
System.out.println(year + "년 " + month + "월 " + day + "일 입니다.");
}else {
System.out.println("유효하지 않은 날짜입니다.");
}
}
}
[ MyDateTest 클래스 ]
package hiding;
public class MyDateTest {
public static void main(String[] args) {
MyDate date = new MyDate();
date.setDay(19);
date.setMonth(1);
date.setYear(2021);
date.showDate();
}
}
< this에 대하여 >
* this의 역할
- 자기 자신의 메모리를 가리킴
- 생성자에서 다른 생성자 호출
public Person(){
this("이름 없음", 1); // 다른 생성자 호출
}
public Person(String name, int age){
this.name = name;
this.age = age;
}
- 인스턴스 자신의 주소를 반환
- 예제
[ Person 클래스 ]
package thisex;
public class Person {
String name;
int age;
public Person() {
//age = 100; //this로 다른 생성자 호출시 this가 firstStatement여야함!!!
this("이름없음", 1);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void showInfo() {
System.out.println(name + ", " + age);
}
public Person getSelf() { //반환타입은 자신의 클래스
return this;
}
}
[ PersonTest 클래스 ]
package thisex;
public class PersonTest {
public static void main(String[] args) {
Person personNoname = new Person();
personNoname.showInfo();
Person personLee = new Person("Lee", 20);
personLee.showInfo();
System.out.println(personLee);
Person p = personLee.getSelf();
System.out.println(p); //this가 가리키는 것과 참조변수가 가리키는 것이 같다.
}
}
/*
결과:
이름없음, 1
Lee, 20
thisex.Person@6a5fc7f7
thisex.Person@6a5fc7f7
*/
< 객체 간 협력 >
* 객체 간 협력
- 객체 지향 프로그램은 객체를 정의하고 객체간의 협력을 구현한 프로그램
- 예제
[ Student 클래스 ]
package cooperation;
public class Student {
String studentName;
int grade;
int money;
public Student(String studentName, int money) {
this.studentName = studentName;
this.money = money;
}
public void takeBus(Bus bus) { //객체 협업, 매개변수로 객체를 받음
bus.take(1000); //bus 인스턴스가 없다면 널포인트익셉션이 떨어질 것임
this.money -= 1000;
}
public void takeSubway(Subway subway) { //객체 협업
subway.take(1200);
this.money -= 1200;
}
public void showInfo() {
System.out.println(studentName + "님의 남은 돈은 " + money + "원 입니다.");
}
}
[ Bus 클래스 ]
package cooperation;
public class Bus {
int busNumber;
int passengerCount;
int money;
public Bus(int busNumber) {
this.busNumber = busNumber;
}
public void take(int money) { //승차
this.money += money;
passengerCount++;
}
public void showBusInfo() {
System.out.println(busNumber + "번 버스의 승객은 " + passengerCount + "명 이고, 수입은 " + money + "입니다.");
}
}
[ Subway클래스 ]
package cooperation;
public class Subway {
int lineNumber;
int passengerCount;
int money;
public Subway(int lineNumber) {
this.lineNumber = lineNumber;
}
public void take(int money) {
this.money += money;
passengerCount++;
}
public void showSubwaysInfo() {
System.out.println(lineNumber + "번 지하철의 승객은 " + passengerCount + "명 이고, 수입은 " + money + "입니다.");
}
}
[ TakeTransTest 클래스 ]
package cooperation;
public class TakeTransTest {
public static void main(String[] args) {
Student studentJ = new Student("James", 5000);
Student studentT = new Student("Tomas", 10000);
Bus bus100 = new Bus(100);
Bus bus500 = new Bus(500);
Subway subwayGreen = new Subway(2);
Subway subwayBlue = new Subway(4);
studentJ.takeBus(bus100);
studentT.takeSubway(subwayGreen);
studentJ.showInfo();
studentT.showInfo();
bus100.showBusInfo();
bus500.showBusInfo();
subwayGreen.showSubwaysInfo();
}
}
< 코딩해보세요 >
1. 정보은닉 - 날짜의 유효성을 검증하는 프로그램 구현하기
* 내 코드
[ MyDate 클래스 ]
package date;
public class MyDate {
private int day;
private int month;
private int year;
public boolean isValid = true;
public int getDay() {
return day;
}
public void setDay(int day) {
if((year % 4 == 0 && year % 100 != 0) ||
( year % 4 == 0 && year % 100 == 0 && year % 400 == 0)){//윤년
switch(month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if (day < 1 || day > 31)
isValid = false;
break;
case 2:
if (day < 1 || day > 29)
isValid = false;
break;
case 4: case 6: case 9: case 11:
if (day < 1 || day > 30)
isValid = false;
break;
}//switch
}else{ //평년
switch(month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if (day < 1 || day > 31)
isValid = false;
break;
case 2:
if (day < 1 || day > 28)
isValid = false;
break;
case 4: case 6: case 9: case 11:
if (day < 1 || day > 30)
isValid = false;
break;
}
}//else끝
if(isValid)
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
if(0 < month && 13 > month)
this.month = month;
else
isValid = false;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public void getMydateInfo() {
if(isValid)
System.out.println(year + "년" + month + "월" + day + "일 입니다.");
else
System.out.println("유 효 N O ");
}
}
[ MyDateTest 클래스 ]
package date;
public class MyDateTest {
public static void main(String[] args) {
MyDate mydate = new MyDate();
mydate.setYear(2021);
mydate.setMonth(2);
mydate.setDay(29);
mydate.getMydateInfo();
}
}
* 모범답안 코드
[ MyDate 클래스 ]
package date;
import java.util.Calendar;
public class MyDate {
private int day;
private int month;
private int year;
private boolean isValid = true;
public MyDate(int day, int month, int year) { //생성자
setYear(year);
setMonth(month);
setDay(day);
}
public int getDay() {
return day;
}
public void setDay(int day) {
switch(month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if (day < 0 || day > 31)
isValid = false;
else
this.day = day;
break;
case 4: case 6: case 9: case 11:
if (day < 0 || day > 30)
isValid = false;
else
this.day = day;
break;
case 2:
if( (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) ) { //윤년
if (day < 0 || day > 29)
isValid = false;
else
this.day = day;
}else { //평년
if (day < 0 || day > 28)
isValid = false;
else
this.day = day;
}
break;
default:
isValid = false;
}
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
if(month < 1 || month > 12)
isValid = false;
else
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
if(year > Calendar.getInstance().get(Calendar.YEAR)) {
isValid = false;
}else
this.year = year;
}
public String isValid() {
if(isValid)
return "유효한 날짜입니다.";
else
return "유효하지 않은 날짜입니다.";
}
}
[ MyDateTest 클래스 ]
package date;
public class MyDateTest {
public static void main(String[] args) {
MyDate date1 = new MyDate(19, 1, 2012);
System.out.println(date1.isValid());
MyDate date2 = new MyDate(6, 10, 1992);
System.out.println(date1.isValid());
}
}
2. 객체 간 협력 - 출근길 커피 사기
* 내 코드
[ Person 클래스 ]
package coffee;
public class Person {
String personName;
int money;
String coffee;
public Person(String personName, int money) {
this.personName = personName;
this.money = money;
}
public void visitStar(StarCoffee star, String coffee) {
money -= star.buyCoffee(coffee);
this.coffee = coffee;
}
public void visitKong(KongCoffee kong, String coffee) {
money -= kong.buyCoffee(coffee);
this.coffee = coffee;
}
public void getPersonCoffeeInfo() {
System.out.println(personName + "씨가 마신 음료는 " + coffee + "이며, 남은 금액은 " + money + "입니다.");
}
}
[ StarCoffee 클래스 ]
package coffee;
public class StarCoffee {
int income;
public int buyCoffee(String coffee) {
if (coffee.equals("아메리카노")) {
income += 4000;
return 4000;
}
else if(coffee.equals("라떼")) {
income += 4500;
return 4500;
}
else return 0;
}
}
[ KongCoffee 클래스 ]
package coffee;
public class KongCoffee {
int income;
public int buyCoffee(String coffee) {
if (coffee.equals("아메리카노")) {
income += 4000;
return 4000;
}
else if(coffee.equals("라떼")) {
income += 4500;
return 4500;
}
else return 0;
}
}
[ CoffeeTest 클래스 ]
package coffee;
public class CoffeeTest {
public static void main(String[] args) {
Person kim = new Person("김졸려", 10000);
Person Lee = new Person("이피곤", 10000);
kim.visitStar(new StarCoffee(), "아메리카노");
Lee.visitStar(new StarCoffee(), "라떼");
kim.getPersonCoffeeInfo();
Lee.getPersonCoffeeInfo();
}
}
/*
결과:
김졸려씨가 마신 음료는 아메리카노이며, 남은 금액은 6000입니다.
이피곤씨가 마신 음료는 라떼이며, 남은 금액은 5500입니다.
*/
'JAVA 문법' 카테고리의 다른 글
Ch07. 상속과 다형성 (1) (0) | 2021.01.22 |
---|---|
Ch06. 배열(2) (0) | 2021.01.20 |
Ch06. 배열(1) (0) | 2021.01.19 |
Ch05. 클래스와 객체(3) (0) | 2021.01.19 |
Ch05. 클래스와 객체(1) (0) | 2021.01.18 |