본문 바로가기
Study in Bootcamp/회고

Day 13 자바 JAVA 이론 (상속, 캡슐화)

by Bhinney 2022. 7. 11.

2022.07.11


1. 오늘의 학습

  • 상속
  • 포함
  • super와 super()
  • 캡슐화
  • setter와 getter

2. 학습 내용

상속(Inheritance)

1) 상속이란
     • 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 자바의 문법적인 요소

2) 상속을 사용하는 이유
     • 코드를 재사용하여 보다 효율적으로 새로운 클래스를 작성하며, 코드의 중복 사용 방지
     • 다향적 표현이 가능

3) 사용방법 :  class 상속이름 extends 클래스이름
public class CityExample {
    public static void main(String[] args){

        Seoul S = new Seoul();
        S.country = "Korea";
        S.name = "Seoul";
        S.capital();
        S.history();
        System.out.println(S.name);
    }
}

class City{
	String country;
   	String name;
    
    	void capital(){System.out.println("수도입니다.")}
}

class Seoul extends City{ // class 상속이름 extends 클래스이름
	void history(){System.out.println("조선 시대에도 수도였습니다.")}
}

/* 출력
수도입니다.
조선시대에도 수도였습니다.
Seoul
*/

cf) 포함(Composite)
        • 클래스의 멤버로 다른 클래스 타입의 참조 변수를 선언하는 것
        • 객체지향에서는 상속보다는 포함을 많이 사용
        • '~은 ~이다' (is) --> 상속 사용
        • '~은 ~을 가지고 있다' (has) --> 포함 사용

public class Citizen {
    String name;
    Address address;
    int age;

    public Citizen(String name, Address address, int age){
        this.name = name;
        this.address = address;
        this.age = age;
    }

    void Infor(){
        System.out.println("이름 : " + name);
        System.out.println("나이 : " +  age);
        System.out.println("사는 도시/ 나라 : " + address.city + "/ " + address.country);
    }

    public static void main(String[] args){
        Address add1 = new Address("Seoul", "Korea");
        Address add2 = new Address("New York", "America");

        Citizen citizen1 = new Citizen("Hanna", add1, 20);
        Citizen citizen2 = new Citizen("Emily",add2,26);

        citizen1.Infor();
        System.out.println("-------------------------------------");
        citizen2.Infor();
    }
}

class Address{
    String city, country;

    public Address(String city, String country){
        this.city = city;
        this.country = country;
    }
}

/* 출력
이름 : Hanna
나이 : 20
사는 도시/ 나라 : Seoul/ Korea
-------------------------------------
이름 : Emily
나이 : 26
사는 도시/ 나라 : New York/ America
*/


4) 메서드 오버라이딩(method overriding)
     • 상위 클래스로부터 상속받은 메서드와 동일한 이름의 메서드를 재정의하는 것
     • 메서드 오버라이딩의 조건
          1️⃣ 메서드의 선언부(메서드 이름, 매개 변수, 반환타입)이 상위 클래스와 일치해야함
          2️⃣ 접근 제어자의 범위가 상위 클래스보다 같거나 넓어야 함
          3️⃣ 예외는 상위 클래스보다 메서드를 많이 선언할 수 없음
class City{
     String country;
     String name;

     void capital(){System.out.println("수도입니다.");}

}

class Seoul extends City{
     void history(){System.out.println("조선시대에도 수도였습니다.");}
}

class NY extends City{
     void capital(){System.out.println("수도가 아닙니다.");} // 오버라이딩
}

public class CityExample {
   public static void main(String[] args){

       Seoul S = new Seoul();
       S.country = "Korea";
       S.name = "Seoul";
       S.capital();
       S.history();
       System.out.println(S.name);

       System.out.println("---------------------------------");

       NY ny = new NY();
       ny.name = "New York";
       ny.capital();
       System.out.println(ny.name);

    }
}

/* 출력
수도입니다.
조선시대에도 수도였습니다.
Seoul
---------------------------------
수도가 아닙니다. ---> capital을 호출했음, 하위 클래스에 재정의 된 것으로 오버라이딩
New York
*/
super
     •상위 클래스의 객체
public class CityExample3 {
    public static void main(String[] args){
        Tokyo t = new Tokyo();
        t.calling();
    }
}

class City3{
    String capital3 = "수도"; //super.capital
}

class Tokyo extends City3{
    String capital3 = "도쿄"; //this.capital

    void calling(){
        System.out.println("capital : " + capital3);
        System.out.println("this.capital : " + this.capital3); // 호출된 인스턴스 변수
                             
                //super.을 붙이지 않는다면 해당 객체는 자신이 속한 인스턴스의 객체의 멤버를 먼저 참조
        System.out.println("super.capital : " + super.capital3); // 상위 클래스 변수
    }
}

/* 출력
capital : 도쿄
this.capital : 도쿄
super.capital : 수도
*/​

super()
     • 상위 클래스의 생성자 호출
     • super()의 사용 조건
          1️⃣ 생성자 안에서만 사용 가능
          2️⃣ 무조건 첫 줄에 와야함
     • 만약 super()가 없으면, 컴파일러가 자동으로 첫 줄에 삽입.
       (이때, 상위 클래스가 없으면 에러 발생.)

public class CityExample4 {
    public static void main(String[] args){
        London l = new London();
    }
}

class City4{
    City4(){
        System.out.println("도시입니다.");
    }
}

class London extends City4{
    London(){ // 생성자 안
        super(); //첫 번째 줄
        System.out.println("영국의 수도입니다.");
    }
}

/* 출력
도시입니다. ---> 상위 클래스(City4)의 생성자를 호출
영국의 수도입니다.
*/
object 클래스
     • 최 상위에 위치한 클래스
     • 자바의 모든 클래스는 object클래스로부터 확장
class City{
	/* 자바가 extends object를 자동 추가
       예제에서 상위 클래스의 안의 내용을 작성하지 않고 빈 괄호로 냅둬도 돌아가는 것을 확인할 수 있음 */
}
class Seoul extends City{
}

//예시 수정 --> 해볼 때는 주석처리해서 돌려보기
public class CityExample4 {
    public static void main(String[] args){
        London l = new London();
    }
}

class City4{ }

class London extends City4{
     London(){System.out.println("영국의 수도입니다."); }
}
/* 출력
영국의 수도입니다.
*/
캡슐화(Encapsulation)

1) 캡슐화란
     • 특정 객체 안에 관련된 속성과 기능을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것
     • 캡슐화의 장점 : 정보 은닉

2) 캡슐화의 목적
     1️⃣ 데이터 보호의 목적
     2️⃣ 내부적으로만 사용되는 데이터에 대한 불필요한 외부노출 방지

3) 패키지(package)
     •특정한 목적을 공유하는 클래스와 인터페이스의 묶음
package _20220711.example; // 패키지 구문, 만일 패키지가 없다면 필요없다

public class Country { }

     • 클래스 패키지 예시 :  java.lang, java.util,  java.io,  java.nio
                                        ---> 이렇게 클래스를 패키지로 묶으면, 클래스의 충돌을 방지해 줌
                                        (이름이 같아도 다른 클래스면, 충돌 X)
     • import 문 

//import 패키지이름.클래스이름; or import 패키지이름.*;
import _20220711.example.Country; 
//혹은 import _20220711.example.*; --> 모든 해당 패키지에서 모든 클래스를 패키지이름 없이 사용 가능

public class test2 {
    public static void main(String[] args){ }
}
제어자(Modifier)

1) 제어자란
     • 클래스, 필드, 메서드, 생성자 등에 부가적인 의미를 부여하는 키워드
     • 제어자 구분
          1️⃣ 접근 제어자 : public, protected, (default), private
          2️⃣ 기타 제어자 : static, final, abstract, native, transient, synchronized 등
          ※ 하나의 대상에 여러 제어자를 사용할 수 있지만, 접근 제어자는 단 한 번만 사용 가능

2) 접근 제어자(access modifier)
     • 클래스 외부로의 불필요한 데이터 노출을 방지(data hiding)
     • 외부로부터 데이터가 임의로 변경되지 않도록 막을 수 있음
❗️ public(접근 제한 ❌) > protected(동일 패키지 + 하위클래스 內) > default(동일 패키지 內)) > private(동일 클래스 內))❗️
setter
     •외부에서 접근하여 조건에 맞을 경우, ‘데이터의 값을 변경 가능하게’ 해줌
     • 'set-'을 메서드이름 앞 에 붙여 정의

getter
     • setter메서드로 ‘설정한 변수의 값을 읽어오는 데’ 사용
     • 'get-'을 메서드이름 앞 에 붙여 정의

package _20220711;

public class Nation {
    public static void main(String[] args){
        Person p = new Person();

        p.setName("하나"); // private을 사용해 변경이 안되나, setter를 사용해 변경 가능
        p.setAge(20);
        p.setCountry("한국");

        String name = p.getName(); // setter로 설정한 걊을 호출
        System.out.println("이름은 " + name + "(이)고, ");

        int age = p.getAge();
        System.out.println("나이는 " + age + "세이고, ");

        String country = p.getCountry();
        System.out.println("사는 나라는 " + country + "(이)다.");
    }
}

class Person{
    private String name; //private 사용
    private int age;
    private String country;

    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }

    public int getAge(){
        return age;
    }
    public void setAge(int age){
        if(age < 1) return;
        this.age = age;
    }

    public String getCountry(){
        return country;
    }
    public void setCountry(String country){
        this.country = country;
    }
}

/* 출력
이름은 하나(이)고, 
나이는 20세이고, 
사는 나라는 한국(이)다.
*/​

3. 돌아보기

오늘 키워드는 이론은 조금은 이해 되는데, 적용함에 있어서 어려웠다. 새롭게 코드를 입력하면서 따라가다보니 계속해서 에러도 나고, 중간 중간 이해하기 위해 멈췄다가 다시 진행하였다. 처음에 상속이름을 나중에 쓰기도 하고, 호출 할 때 생성자를 초기화 해놓고 제대로 부르지 않아 오래 헤매기도 했다. 그래도 주어진 시간이 많아 처음부터 차례차례 비교하면서 다시 코드를 쓰고, 쓰기 전에 이해도 하고, 쓰고나서도 해석하면서 진행을 했다.  점점 늘어나니 수도코드의 중요성이 느껴지는 것 같다. 내일부터는 제대로 설계를 짜고 따라해야겠다. 그동안은 수도코드를 적기보다 입으로 얘기만 하고 넘어갔으나, 꼭 적어야하는 걸 느꼈고 습관화 할 필요가 있음을 느꼈다.

 

 

댓글