예를 들어 학생이 수강한 과목들에 대한 점수를 산출하기 위한 경우
학생 클래스
학번
학생이름
국어과목
수학과목
(+)
과목 클래스
과목이름
과목 점수
참조 자료형으로 멤버변수를 사용하는 경우 대부분 생성자에서 생성됨.
반드시 생성자에서 생성해야하는건 아니며, 사용되기 전에만 생성되면 됨.(생성되기 전 사용 시 nullpointerexception에러
발생)
-Subject.java-
package ch09;
public class Subject {
String subjectName;
int score;
int subjectId;
}
-Student.java-
package ch09;
public class Student {
int studentId;
String studentName;
Subject korea;
Subject math;
Student(int studentId, String studentName) {
this.studentId = studentId;
this.studentName = studentName;
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 showScoreInfo() {
int total = korea.score + math.score;
System.out.println(studentName + "학생의 총점은 " + total + "점 입니다.");
}
}
-StudentTest.java-
package ch09;
public class SubjectTest {
public static void main(String[] args) {
Student studentLee = new Student(100, "Lee");
studentLee.setKoreaSubject("국어", 100);
studentLee.setMathSubject("수학", 80);
Student studentKim = new Student(200, "Kim");
studentLee.setKoreaSubject("국어", 96);
studentLee.setMathSubject("수학", 75);
studentLee.showScoreInfo();
studentKim.showScoreInfo();
}
}
접근 제어 지시자(access modifier)와 정보은닉(infomation hiding)
키워드 목록
private
: 같은 클래스 내에서만 접근가능(default)
: 같은 패키지 내에서만 접근가능 (상속관계라도 패키지가 다를 경우 접근불가)protected
: 같은 패키지이거나 상속관계의 클래스에서만 접근가능public
: 클래스 외부 어디서든 접근가능default
상태에서 다른 패키지에 속해있을 경우 import
를 하여 사용함.
예) scanner클래스는 java.util패키지에 속해있으므로 사용하려면 import과정을 거쳐야 함
private
로 선언된 멤버변수(필드)에 대해 접근, 수정 할 수 있는 메서드를 public으로 제공=> 멤버변수에 직접 값을 넣을 경우 생기는 데이터의 불필요한 오용을 메서드를 이용해 막을 수 있음.
-BirthDay.java-
package ch10;
public class BirthDay {
private int day;
private int month;
private int year;
private boolean isValid;
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
if(month < 1 || month > 12) {
isValid = false;
} else {
isValid = true;
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("유효하지 않은 날짜입니다.");
}
}
}
-BirthDayTest.java-
package ch10;
public class BirthDayTest {
public static void main(String[] args) {
BirthDay date = new BirthDay();
date.setYear(2022);
date.setMonth(13);
date.setDay(22);
date.showDate();
date.setMonth(8);
date.showDate();
//date.month = 100; // 직접 멤버변수에 값을 넣을 경우 데이터에 대한 제어가 불가능함
}
}
date.month = 100;
(에러발생) => BirthDay클래스에서 private
로 멤버변수의 접근제어자를 지정하여 다른 클래스에서 객체를 생성하더라도 멤버변수에 직접 접근하여 값을 지정할 수 없다.
단, 무조건 private
키워드를 사용하는것은 바람직하지 않음.
상황에 따라 공개여부 및 단계에 따라 지정해야 함.
이클립스에서 getter setter 자동생성기능을 지원함
-MakeReport.java-
package ch11;
public class MakeReport {
StringBuffer buffer = new StringBuffer();
private String line = "===========================================\n";
private String title = " 이름\t 주소 \t\t 전화번호 \n";
private void makeHeader()
{
buffer.append(line);
buffer.append(title);
buffer.append(line);
}
private void generateBody()
{
buffer.append("James \t");
buffer.append("Seoul Korea \t");
buffer.append("010-2222-3333\n");
buffer.append("Tomas \t");
buffer.append("NewYork US \t");
buffer.append("010-7777-0987\n");
}
private void makeFooter()
{
buffer.append(line);
}
public String getReport()
{
makeHeader();
generateBody();
makeFooter();
return buffer.toString();
}
}
-TestReport.java-
package ch11;
public class TestReport {
public static void main(String[] args) {
MakeReport report = new MakeReport();
String builder = report.getReport();
System.out.println(builder);
}
}
클라이언트에게는 getReport()
메서드만을 제공하여 출력하는 기능만을 사용할 수 있도록 함.
순서를 지정하는 기능 등은 캡슐화하여 사용자에게 기능을 숨김.
어떤 기능 및 객체를 얼마나 공개하고 어떤 정보를 숨기느냐를 설계하는 것이 객체지향 설계에서 매우 중요한 부분임.
super
와 동일)상속에서의 super와 유사하므로 반드시 알아두자.
public void setYear(int year)
{
this.year = year;
}
public class Person {
String name;
int age;
public Person() {
//name = "이름"; 아직 인스턴스의 생성이 완료되지 않아 에러발생. 생성 후 사용은 가능.
this("no name", 1);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void showPerson() {
System.out.println(name + ", " + age);
}
public static void main(String[] args) {
Person person = new Person();
person.showPerson();
}
}
public class Person {
String name;
int age;
public Person() {
//name = "이름"; 아직 인스턴스의 생성이 완료되지 않아 에러발생. 생성 후 사용은 가능.
this("no name", 1);
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void showPerson() {
System.out.println(name + ", " + age);
}
public Person getPerson() {
return this;
}
public static void main(String[] args) {
Person person = new Person();
person.showPerson();
System.out.println(person);
Person person2 = person.getPerson();
System.out.println(person2);
}
}
person
과 person2
는 같은 주소값이 반환됨.
객체지향 프로그래밍은 실생활을 잘 반영한 프로그래밍 방식임.
James와 Tomas는 각각 버스와 지하철을 타고 학교에 갑니다.
James는 5000원을 가지고 있었고, 100번 버스를 타면서 1000원을 지불합니다.
Tomas는 10000원을 가지고 있었고, 초록색 지하철을 타면서 1200원을 지불합니다.
-Student.java-
public class Student {
String studentName;
int money;
public Student(String studentName, int money) {
this.studentName = studentName;
this.money = money;
}
public void takeBus(Bus bus) {
bus.take(1000);
this.money -= 1000;
}
public void takeSubway(Subway subway) {
subway.take(1200);
this.money -= 1200;
}
public void showInfo() {
System.out.println(studentName + "님의 남은 돈은 " + money + "원 입니다.");
}
}
-Bus.java-
public class Bus {
int busNum; // 버스번호
int passengerCount; // 승객 수
int money; // 수입
public Bus(int busNum) {
this.busNum = busNum;
}
public void take(int money) {
this.money += money;
passengerCount++;
}
public void showBusInfo() {
System.out.println(busNum + "번 버스의 승객 수는 " + passengerCount + "명이고 수입은 " + money + "원 입니다.");
}
}
-Subway.java-
public class Subway {
int lineNum; // 라인번호
int passengerCount; // 승객 수
int money; // 수입
public Subway(int lineNum) {
this.lineNum = lineNum;
}
public void take(int money) {
this.money += money;
passengerCount++;
}
public void showBusInfo() {
System.out.println(lineNum + "번 지하철의 승객 수는 " + passengerCount + "명이고 수입은 " + money + "원 입니다.");
}
}
-TakeTransTest.java-
public class TakeTransTest {
public static void main(String[] args) {
Student studentJ = new Student("제임스", 5000);
Student studentT = new Student("토마스", 10000);
Bus bus100 = new Bus(100);
Bus bus200 = new Bus(200);
studentJ.takeBus(bus100);
studentJ.showInfo();
Subway greenSubway = new Subway(2);
studentT.takeSubway(greenSubway);
studentT.showInfo();
bus100.showBusInfo();
greenSubway.showBusInfo();
}
}
앞의 예제에서 Edward는 지각을 해서 택시를 타야 했습니다.
20000원을 가지고 있었는데 10000원을 택시비로 사용했습니다.
택시는 '잘나간다 운수' 회사 택시를 탔습니다.
틀릴 수 있음
택시클래스를 만들어 택시를 타는 메서드를 만듦
고객클래스를 만들어 이름과 총금액을 멤버변수로 생성
고객클래스에서 택시클래스의 택시를 타는 메서드를 호출하여 총금액을 다시계산
-Customer.java-
public class Customer {
String name;
int money;
public Customer(String name, int money) {
this.name = name;
this.money = money;
}
public void takeTaxi(Taxi taxi) {
taxi.take(2000);
this.money -= 2000;
}
public void showCustomerInfo() {
System.out.println(name + "님의 남은 돈은 " + money + "원 입니다.");
}
}
-Taxi.java-
public class Taxi {
String taxiName;
int money;
public Taxi(String taxiName) {
this.taxiName = taxiName;
}
public void take(int money) {
this.money += 2000;
}
public void showTaxiInfo() {
System.out.println(taxiName + "택시의 수입은 " + money + "원 입니다.");
}
}
-TakeTaxiTest.java-
public class TakeTaxiTest {
public static void main(String[] args) {
Customer customer01 = new Customer("에드워드", 10000);
Taxi taxi01 = new Taxi("잘나간다 운수");
customer01.takeTaxi(taxi01);
customer01.showCustomerInfo();
taxi01.showTaxiInfo();
}
}