어제 의도치 않게 접근제어자와 getter/setter에 대해 공부 했더니 오늘 강의를 따라가는게 쉬웠다.
이렇게 깔끔하게 이해되고, 편안하게 공부했던적이 정말 오랜만인듯 하다...
예습의 필요성을 이렇게 또 깨닫게 되는 좋은 예시가 됐다고 생각한다.
물론 복습도 중요하지만, 하나도 모르는 것을 혼자 생각해 보고 이해해 보는 과정은 너무나 필요한 일 이라는 생각이 든다.
# 상속 (Inheritance)
- 상위 클래스 - 하위 클래스의 상속 관계의 핵심을 이해하고, 그 장점을 설명할 수 있다.
- extends 키워드를 사용하여 두 개 이상의 클래스 간 상속 관계를 정의 할 수 있다.
- 포함관계과 상속관계의 차이를 설명할 수 있다.
- 상속 관계에서 사용할 수 있는 메서드 오버라이딩의 정의, 성립 조건, 장점을 이해하고 이를 활용할 수 있다.
- super와 super()의 차이를 설명할 수 있다.
- Object 클래스가 자바 클래스의 상속계층도 상에서 최상단에 위치한다는 사실을 이해할 수 있다.
# 캡슐화 (Encapsulation)
- 캡슐화의 핵심 개념과 목적을 이해하고 설명할 수 있다.
- 패키지의 개념과 import 문이 어떻게 사용되는 지 이해할 수 있다.
- 자바에서 캡슐화를 달성하기 위한 핵심적인 수단인 접근제어자 네가지를 이해하고, 접근 가능 범위를 설명할 수 있다.
- 데이터를 효과적으로 보호하기 위한 수단인 getter/setter 메서드를 이해하고 사용할 수 있다.
1. 상속이란?
: 기존의 클래스를 재 활용하여 새로운 클래스를 작성하는 자바의 문법요소
: 하위 클래스(자식)는 상위 클래스(부모)가 가진 모든 멤버를 상속(확장)받음
→ 하위클래스의 멤버개수 >= 상위클래스 멤버개수
→ extends 부모클래스명
→ 하나의 객체는 하나의 부모만 참조 가능
- 상속을 사용하는 이유
: 코드를 재 사용해서, 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있어서
→ 중복코드 제거
- 다형성
: 상속은 다형적 표현이 가능
→ 하나의 객체가 여러가지로 표현되는 것
- 키워드 사용법
: extends 부모클래스명 으로 사용
: 키워드??
→ 이미 어딘가에 지정되어(만들어져 있는것)
→ public, static, int, string ...
→ 변수명이나 메서드명으로 사용 불가능
2. 포함 관계
: 상속처럼 클래스를 재 사용할 수 있는 방법
→ 클래스의 멤버로 다른 클래스 타입의 참조변수를 선언하는 것
public class Employee {
int id;
String name;
Address address;
// 3. Employee클래스 에 참조변수를 선언하는 방법으로 코드의 중복을 없앰
public Employee(int id, String name, Address address) {
this.id = id;
this.name = name;
this.address = address;
}
void showInfo() {
System.out.println(id + " " + name);
System.out.println(address.city+ " " + address.country);
}
public static void main(String[] args) {
Address address1 = new Address("서울", "한국");
Address address2 = new Address("도쿄", "일본");
Employee e = new Employee(1, "김코딩", address1);
Employee e2 = new Employee(2, "박해커", address2);
e.showInfo();
e2.showInfo();
}
}
// 1. 원래라면 Address 클래스의 String city, country를 위 Employee클래스에 각각 객체를 만들어 변수로 정의해 줘야 함
class Address {
String city, country;
// 2. 하지만 Address 클래스로 해당 변수를 묶어 주고
public Address(String city, String country) {
this.city = city;
this.country = country;
}
}
- 상속과 포함 중 어떤걸 사용?
: 클래스 간의 관계가 '~은 ~이다 (IS-A)' [Employee는 Address이다. / Employee는 Address를 가지고 있다.]
→ 포함관계
: 클래스 간의 관계가 '~은 ~을 가지고 있다 (HAS-A)' [SpotrCar는 Car이다. / SpotrCar는 Car를 가지고 있다.]
→ 상속관계
3. 메서드 오버라이딩 (Method Overriding : ~ 위에 덮어 쓰다)
: 상위 클래스로부터 상속 받은 메서드와 동일한 이름의 메서드를 재 정의 하는 것
public class Main {
public static void main(String[] args) {
Bike bike = new Bike();
Car car = new Car();
MotorBike motorBike = new MotorBike();
// 3. 1번의 값이 아닌 각각의 run 값을 덮어 씌워 호출
bike.run();
car.run();
motorBike.run();
}
}
// 1. Vehicle 클래스에 void run의 값이 정의 되어 있음
class Vehicle {
void run() {
System.out.println("Vehicle is running");
}
}
// 2. 아래에 각각 Bike, Car, MotorBike 클래스에서 다시 void run의 값을 정의하니
class Bike extends Vehicle {
void run() {
System.out.println("Bike is running");
}
}
class Car extends Vehicle {
void run() {
System.out.println("Car is running");
}
}
class MotorBike extends Vehicle {
void run() {
System.out.println("MotorBike is running");
}
}
- 상위 클래스의 메서드를 오버라이딩 하려면
→ 매서드의 선언부(메서드 이름, 매개변수, 반환타입)가 상위클래스와 일치
→ 접근 제어자의 범위 >= 상위 클래스의 메서드
→ 예외는 상위 클래스의 메서드보다 많이 선언할 수 없음
4. super키워드, super()
: 상위 클래스의 존재를 상정하며 상속관계를 전제로 함
- super
: 상위 클래스의 객체 호출
→ 같은 이름의 변수를 위치로 구분하기 위함
public class Example {
public static void main(String[] args) {
SubClass subClassInstance = new SubClass();
subClassInstance.callNum();
}
}
class SuperClass {
int count = 20; // super.count
}
class SubClass extends SuperClass {
int count = 15; // this.count
void callNum() {
System.out.println("count = " + count); // 가장 가까운 count 값
System.out.println("this.count = " + this.count); // 자신이 속한 인스턴스의 count 값
System.out.println("super.count = " + super.count); // 상위 클래스의 count 값
}
- super()
: 상위 클래스의 생성자 호출
→ 생성자의 첫 줄에 반드시 선언 되어야 함
public class Test {
public static void main(String[] args) {
Student s = new Student();
}
}
class Human {
Human() {
System.out.println("휴먼 클래스 생성자");
}
}
class Student extends Human { // Human 클래스로부터 상속
Student() {
super(); // Human 클래스의 생성자 호출
// 상위 클래스에 기본 생성자가 없다면 컴파일 오류가 남(항상 기본 생성자가 필요)
// super()를 안써도 자바에서 알아서 붙여줌
System.out.println("학생 클래스 생성자");
}
}
5. Object 클래스
: 상속 계층도의 최상위에 위치 / 자바의 모든 클래스는 Object 클래스로부터 확장
→ 컴파일러가 자동으로 상속시킴
- 메서드 종류
메서드 명 | 반환 타입 | 내용 |
toString() | String | 객체 정보를 문자열로 출력 |
equals(Object obj) | boolean | 등가 비교 연산(==)과 동일하게 스택 메모리값을 비교 |
hashCode() | int | 객체의 위치정보 관련. Hashtable 또는 HashMap에서 동일 객체여부 판단 |
wait() | void | 현재 스레드 일시정지 |
notify() | void | 일시정지 중인 스레드 재동작 |
1. 캡슐화 란?
: 특정 객체 안에 관련된 속성과 기능을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것
: 객체지향에서 핵심적인 내용
: 객체의 상태나 내부동작 ( 필드, 메서드, 멤버)을 감추는 것
→ 데이터 보호
→ 내부데이터의 불필요한 외부노출 방지
→ 가장 큰 장점 (정보 은닉)
2. 패키지
: 특정한 목적을 공유하는 클래스와 인터페이스의 묶음
: 클래스를 그룹 단위로 묶어 효과적으로 관리하기 위함
: 하나의 디렉토리 (direcrory)
→ 계층구조를 가지며, 구분은 닷(점 . )으로 표현
package practicepack.test; // 패키지 구문 포함. 패키지가 없다면 구문 필요없음
public class PackageEx {
}
→ 클래스의 충돌을 방지하는 기능 (같은 이름의 클래스더라도 패키지가 다르면 충돌이 발생하지 않음)
- Import 문
: 다른 패키지 내의 클래스를 사용하기 위해 사용됨
→ 패키지 구문 - Import 문(사이에 작성) - 클래스 문
→ import문이 없다면 클래스에 매번 패키지 명을 붙여 주어야 함
import 패키지 명.클래스 명;
// import 문을 사용하지 않는 경우, 다른 패키지 클래스 사용방법
package practicepack.test2;
public class PackageImp {
public static void main(String[] args) {
practicepack.test.ExampleImport example = new practicepack.test.ExampleImport();
}
}
// import 문을 사용하는 경우
package practicepack.test2;
import practicepack.test.ExampleImp // import 문 작성
public class PackageImp {
public static void main(String[] args) {
ExampleImp x = new ExampleImp(); // 이제 패키지 명을 생략 가능
}
}
3. 접근 제어자
- 제어자 (Modifier)
: 클래스, 필드, 메서드, 생성자 등에 부가적인 의미를 부여하는 키워드 (형용사_꾸며주는)
→ 하나의 대상에 여러가지 제어자를 사용할 수 있음
- 접근 제어자
: public, protected, (default), private
→ 단, 접근 제어자는 한 번만 사용 가능
→ 불필요한 데이터 노출 방지, 임의로 데이터가 변경되지 않도록 보호 하는 목적을 가짐
접근 제어자 | 접근 제한 범위 |
private | 동일 클래스에서만 접근 가능 |
default | 동일 패키지 내에서만 접근 가능 |
protected | 동일 패키지 + 다른 패키지의 하위 클래스에서 접근 가능(import, extends) |
public | 접근 제한 없음 |
- 기타 제어자
: static, final, abstract, native, transient, synchronized 등
4. getter / setter와 메서드
: 객체의 변수 데이터 값을 추가하거나 수정하고 싶을 때 사용
: 데이터를 효과적으로 보호하고, 의도한 값으로 변경할 수 있음
public class GetterSetterTest {
public static void main(String[] args) {
Worker w = new Worker(); // Worker w 라는 객체 생성
w.setName("김코딩"); // w.set으로 객체 초기화(초기값 설정)
w.setAge(30);
w.setId(5);
// w.get 으로 설정된 값을 불러옴
String name = w.getName();
System.out.println("근로자의 이름은 " + name);
int age = w.getAge(); // 리턴한 getAge의 값을 불러와서 출력
System.out.println("근로자의 나이는 " + age);
int id = w.getId();
System.out.println("근로자의 ID는 " + id);
}
}
// Worker 클래스 생성
class Worker {
private String name; // 변수의 은닉화. 외부로부터 접근 불가
private int age;
private int id;
public String getName() { // 멤버변수의 값
return name;
}
public void setName(String name) { // 멤버변수의 값 변경
this.name = name;
}
public int getAge() { // setAge의 값을 불러와서 return 함
return age;
}
public void setAge(int age) { // setAge의 입력값이 1보다 작다면 그 값으로 초기화(세팅값 변경)
if(age < 1) return; // 그게 아니라면 메소드 종료(값 변경 없음)
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
- getter
: 설정한 변수의 값을 불러올때(읽어올때) 사용
→ get메서드명
- setter
: 외부에서 privete 메서드에 접근하여 조건에 맞을 경우 데이터 값을 변경 할 수 있도록 함
→ set메서드명
문자열이 같은 것을 검사
.equals
코드를 볼 때 객체가 생성된 곳으로 먼저 감
업캐스팅, 다운캐스팅 : 설계에 따라 어떤게 어디까지 가지고 있을지 설정 하는 것
# 다형성 (Polymorphism)
# 추상화 (Abstraction)
↓ 이전 글 ↓
↓ 코트스테이츠 부트캠프 관련 글 한번에 보기 ↓
[코드스테이츠] 05_01_TIL : 컬렉션 (Collection) (0) | 2023.05.01 |
---|---|
[코드스테이츠] 04_26_TIL : 객체지향 _ 다형성과 추상화 (1) | 2023.04.26 |
[코드스테이츠] 04_24_TIL : 객체지향 _ 생성자와 이너클래스 (0) | 2023.04.24 |
[코드스테이츠] 04_21_TIL : 객체지향 _ 클래스, 객체, 필드, 메서드 (0) | 2023.04.21 |
[코드스테이츠] 04_20_TIL : JAVA 다섯번째 _ 배열 (1) | 2023.04.20 |