GETTER, SETTER, 클래스 작성시 거의 필수적으로 들어감.
필드정보 접근시 사용하는 메소드.
캡슐화(encapsulation)
캡슐화는 객체의 속성(Field)과 행위(Method)를 하나로 묶고, 외부로 부터
내부를 감싸 숨겨 은닉한다.
또한 외부의 잘못된 접근으로 값이 변하는 의도치 않는 동작을 방지하는
보호 효과도 누릴 수 있다.
자바에서는 대표적으로 protected , default , private의 접근 제어자를 통해 구현이 가능하다.
클래스 선언할 때 필드는 일반적으로 private 접근 제한
읽기 전용 필드가 있을 수 있음 (Getter의 필요성)
외부에서 엉뚱한 값으로 변경할 수 없도록 (Setter의 필요성)
Getter:
private 필드의 값을 리턴 하는 역할 - 필요할 경우 필드 값 가공
getFieldName() 또는 isFieldName() 메소드
필드 타입이 boolean 일 경우 isFieldName()
Getter 메서드는 객체의 필드 값(value)을 반환하는 메서드입니다. 이 메서드를 사용하면 객체의 필드 값에 직접 접근하지 않고도 필드 값을 읽어올 수 있습니다.
Setter:
외부에서 주어진 값을 필드 값으로 수정
필요할 경우 외부의 값을 유효성 검사
setFieldName(타입 변수) 메소드
매개 변수 타입은 필드의 타입과 동일
Setter 메서드는 객체의 필드 값을 설정하는 메서드입니다. 이 메서드를 사용하면 객체의 필드 값을 직접 변경할 수 없고, Setter 메서드를 통해 필드 값을 설정해야 합니다.
package encapsulation;
class Student{
public String name; // 이름
private int age; // 나이
private int grade; // 학년
public void setAge(int age) {
if(age < 1) {
System.out.println("등록할 수 없는 나이입니다.");
this.age = 1;
return;
}
this.age = age;
}
public void setGrade(int grade) {
if(grade < 1 || grade > 3) {
this.grade = 1;
return;
}
this.grade = grade;
}
public int getAge() {
return this.age;
}
public int getGrade() {
return this.grade;
}
}
public class StudentTest {
public static void main(String[] args) {
Student stu = new Student();
stu.name = "최기근";
//직접적으로 값대입 불가. set메소드로만 대입가능하다.
// stu.age = -100;
// stu.grade = -8;
stu.setAge(-100);
stu.setGrade(2);
int age = stu.getAge();
int grade = stu.getGrade(); //stu.grade 이렇게 접근 안된다.
System.out.println(age);
System.out.println(grade);
}
}
싱글톤 : 인스턴스 하나가지고 공유하는거.
싱글톤(Singleton)
하나의 애플리케이션 내에서 단 하나만 생성되는 객체
싱글톤을 만드는 방법
외부에서 new 연산자로 생성자를 호출할 수 없도록 막기
private 접근 제한자를 생성자 앞에 붙임
클래스 자신의 타입으로 정적 필드 선언
자신의 객체를 생성해 초기화
private 접근 제한자 붙여 외부에서 필드 값 변경 불가하도록
외부에서 호출할 수 있는 정적 메소드인 getInstance() 선언
정적 필드에서 참조하고 있는 자신의 객체 리턴
package singleton;
import java.util.Calendar;
/**
* 싱글톤 디자인 패턴
* 객체의 인스턴스가 오직 1개만 생성되는 패턴
*/
class Printer{
//직접적으로 접근 못하게 막아놨다.
private static Printer printer;
// 객체 생성은 프린터 내부에서만 호출 가능, 다른 클래스에서 new연산자로 객체 생성 불가
private Printer() {}
//같은 static 멤버 사용 가능. (인스턴스멤버는 사용불가해서 static 멤버 따로 만듬)
public static Printer getInstance() {
if(printer == null) {
printer = new Printer();
}
return printer;
}
public void println(String document) {
System.out.println("문서를 출력합니다.");
System.out.println(document);
System.out.println("문서 출력 완료");
}
}
public class SingletonTest {
public static void main(String[] args) {
// Printer printerA = new Printer();
// //Student stu = new Student();
// printerA.println("A가 가진 프린터기 출력");
// Printer printerB = new Printer();
// printerB.println("B가 가진 프린터기 출력");
Printer printA = Printer.getInstance();
printA.println("A 출력 ");
Printer printB = Printer.getInstance();
printA.println("B 출력 ");
// 둘은 동일한 위치에 저장되어있다.(메모리공간 효율적으로 활용가능)
System.out.println(printA);
System.out.println(printB);
// 현재 시간에 대한 정보를 알려주는 class
//java.util.Calendar
Calendar now = Calendar.getInstance();
// 호출 되는 시점에 시간에 대한 정보를
// 연산에 활용할 수 있도록 제공하는 util class, 정수타입으로 제공
// 년도
int year = now.get(Calendar.YEAR);
// 년 중 월 0 ~ 11- 인덱스 번호로 표현
// 월을 확인 할때는 +1 해서 사용
int month = now.get(Calendar.MONTH);
// 월중 날짜
int day = now.get(Calendar.DAY_OF_MONTH);
// SUNDAY == 1 ... SATURDAY == 7
int week = now.get(Calendar.DAY_OF_WEEK);
System.out.println(Calendar.SUNDAY);
System.out.println(Calendar.SATURDAY);
int hour = now.get(Calendar.HOUR);
int minute = now.get(Calendar.MINUTE);
int second = now.get(Calendar.SECOND);
System.out.printf(
"%d년%d월%d일 %d:%d:%d %n",
year,month,day,hour,minute,second
);
}
}
상속
클래스 상속은 하나만 가능함.
명시적인 부모 생성자 호출:(매개값없으면 생략가능)
부모 객체 생성할 때, 부모 생성자 선택해 호출
super(매개값,…)
매개값과 동일한 타입, 개수, 순서 맞는 부모 생성자 호출
부모 생성자 없다면 컴파일 오류 발생
반드시 자식 생성자의 첫 줄에 위치
부모 클래스에 기본(매개변수 없는) 생성자가 없다면 필수 작성
메소드 재정의(Override)
부모 메소드 사용(super)
메소드 재정의는 부모 메소드 숨기는 효과 !!
자식 클래스에서는 재정의된 메소드만 호출
자식 클래스에서 수정되기 전 부모 메소드 호출 - super 사용
super는 부모 객체 참조(참고: this는 자신 객체 참조)
@Override 어노테이션
컴파일러에게 부모 클래스의 메소드 선언부와 동일한지 검사 지시
정확한 메소드 재정의 위해 붙여주면 OK
메소드 재정의 효과
부모 메소드는 숨겨지는 효과 발생
재정의된 자식 메소드 실행
package extends1_base;
//버스도 차다
class Bus extends Car{
int busNumber;
Bus(){
super("Benz"); //부모생성자 호출
System.out.println("기본생성자 호출");
}
public String showInfo() {
return "Bus : busNumber = "+busNumber + "company: " + company;
}
@Override // 부모에 있는거랑 같은 문법인지 컴파일 단계에서 확인해줌(생략가능)
public String toString() { //오버라이드 할 때는 접근제한자가 부모객체보다 작아질 수 없다.
return "Car[ busNumber = "+busNumber+ ", company = "+company+", speed = "+speed+"]";
}
}
class Taxi extends Car{
Taxi(){
super();
System.out.println("taxi 기본 생성자 호출");
this.company = "기아자동차";
super.speed = 10;
}
}
// 기본적으로 아무것도 상속받지 않으면 extends Object이 생략되어있다.
public class Car //extends Object
{
String company = "현대자동차";
int speed;
public Car() {
this("Benz");// this로 생성자 호출 시 this 생성한 곳에서 부모 호출한다.
// 여기서 super(); 사용 불가
System.out.println("Car 기본 생성자 호출");
}
public Car(String company) {
this.company = company;
System.out.println("company를 넘겨받는 생성자");
}
public String toString() {
return "Car[company = "+company+", speed = "+speed+"]";
}
public static void main(String[] args) {
Car car = new Car();
car.company = "BMW";
car.speed = 100;
System.out.println(car.toString());
Bus bus = new Bus();
bus.company = "현대자동차";
bus.speed = 200;
System.out.println(bus.toString());
Taxi taxi = new Taxi();
System.out.println(taxi.toString());
System.out.println(taxi);
}
}
package extends2_override;
public class Calculator {
// 반지름을 입력받아 원의 넓이를 반환
double circleArea(double radius) {
return radius * radius *3.14;
}
}
package extends2_override;
public class CalculatorExample {
public static void main(String[] args) {
Calculator calc = new Calculator();
double area = calc.circleArea(7);
System.out.println("calc : "+ area);
Computer com = new Computer();
area = com.circleArea(7);
System.out.println("com : "+area);
System.out.println(calc);
System.out.println(com.toString());
}
}
package extends2_override;
public class Computer extends Calculator {
// alt + s + v : 재정의 method 선택창(오버라이드 선택창)
// 부모보다 좁은 범위의 접근 제어자를 사용할 수 없음. - 넓은건 가능
//ex - 부모가 default 일시 default, public 가능
@Override
double circleArea(double radius) {
// return super.circleArea(radius);
return radius * radius * Math.PI;
}
}
다형성
부모타입에는 모든 자식 개체가 대입이 가능하다. (자동타입변환)
부모타입에 정의된 내용만 사용할 수 있다.
ex>
이때 cat == animal // true (실제 생성된게 cat이니까)
단, animal 타입에 정의되어있는 기능만 수행이 가능하다.
package extends3_polymorphism.base;
public class Person {
String name; // 이름
int age; // 나이
int weight; // 몸무게
int height; // 키
// 기본 생성자 - 전체 값을 넘겨받는 생성자 추가
// alt + s + a
public Person() {
super();
}
public Person(String name, int age, int weight, int height) {
super();
this.name = name;
this.age = age;
this.weight = weight;
this.height = height;
}
// Object class의 toString() method 재정의
// alt + s + s + s
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", weight=" + weight + ", height=" + height + "]";
}
}
package extends3_polymorphism.base;
public class PersonExample {
public static void main(String[] args) {
Person person = new Person("최기근",25,68,187);
System.out.println(person);
System.out.println("===================================================");
//student가 Person 상속받고 있으니까 대입 가능.
Person student = new Student(
"최기근",25,74,189,"603호","45번","1학년"
);
//실제로 저장되어있는건 student니까 student의 위치로 가서 메소드 실행.(오버라이드된걸로 실행됨)
System.out.println(student.toString());
//student.study(); 사용불가
System.out.println("====================================");
// 변수가 Person type이면 Person이거나 하위 타입만 대입 가능
//Person obj = new String("최기근");
Object o = student;
System.out.println(o.toString());
//강제타입변환 : 검증한 후 타입변환해야함.
//ClassCastException : 클래스의 타입변환이 잘못되었다.
/*
Student stu = (Student)person;
stu.study();
Student stu2 = (Student)student;
stu2.study();
*/
Student stu;
//(실제 생성된 객체 instanceof 타입) : 해당 타입이면 true / 아니면 false
boolean isPossible = (person instanceof Student);
System.out.println(isPossible);
if(student instanceof Student) {
stu = (Student)student;
stu.study();
}else {
System.out.println("Student 타입이 아닙니다.");
}
}
}
package extends3_polymorphism.base;
public class Student extends Person{
String classRoom; // 강의실
String studentNum; // 학번
String grade; // 학년
// alt + s + a 부모 생성자 매개변수까지 한번에 전달받아서 초기화하고 있음.
public Student(String name, int age, int weight, int height,
String classRoom, String studentNum, String grade) {
super(name, age, weight, height);
this.classRoom = classRoom;
this.studentNum = studentNum;
this.grade = grade;
}
public void study() {
System.out.println(super.name+"학생은 "+grade+"학년 "+classRoom+"에서 공부합니다.");
}
// alt + s + s +s
@Override
public String toString() {
// super.toString() : 부모 클래스에 있는 toString()을 가져온다.
return super.toString()+"Student [classRoom=" + classRoom + ", studentNum=" + studentNum + ", grade=" + grade + "]";
}
}
메소드
package extends3_polymorphism.methods;
//탈것
class Vehicle{
public void run() {
System.out.println("탈것이 달립니다.");
}
}
class Taxi extends Vehicle{
public void run() {
System.out.println("택시가 승객을 모시고 달립니다.");
}
}
class Bus extends Vehicle{
public void run() {
System.out.println("버스가 다수의 승객을 태우고 달립니다.");
}
}
class MotorCycle extends Vehicle{
public void run() {
System.out.println("오토바이가 두바퀴로 달립니다.");
}
}
public class VehicleTest {
// 매개변수가 부모타입, 자식타입 일일이 안만들고 하나로 대체 가능 (매개변수의 다형성)
public static void runVehicle(Vehicle v) {
v.run();
}
/*
public static void runVehicle(Taxi taxi) {
taxi.run();
}
public static void runVehicle(Bus bus) {
bus.run();
}
*/
public static void main(String[] args) {
Taxi taxi = new Taxi();
runVehicle(taxi);
Bus bus = new Bus();
runVehicle(bus);
MotorCycle mc = new MotorCycle();
runVehicle(mc);
}
}
'Java' 카테고리의 다른 글
Book (0) | 2023.05.01 |
---|---|
캡슐화 숙제 (0) | 2023.04.28 |
0427 접근제한자 (0) | 2023.04.27 |
0427 실습 해설 (0) | 2023.04.27 |
04.26 평가 틀린거 (0) | 2023.04.27 |