Study

[Study #13] 접근제어자, STATIC, 상속, 오버라이드, 추상화

PEAZH 2023. 6. 20. 21:32
반응형

 

package interf;

abstract // 인터페이스 만들어보기
//2023-06-21 프로그래밍 언어 활용
//다중 상속 --- 우리가 아는 상속은 단일 상속
//단일 상속을 극복하고자 나온 것이 인터페이스
//인터페이스는 추상 메소드만 들어가요

abstract class Hero {// 추상 클래스 : 인스턴스 X, 상속 용도로만 존재
	String name;

	public abstract void attack();// 추상화 (여기서 완성시켜도 밑에서 완성시킬 거니까 삭제시킴)
	// 추상 메소드 : 상속 받는 자식들은 강제로 구현

	public abstract void eat();//abstract은 리턴타입 앞쪽에 적어주기

	public abstract void sleep();
	
	
}
//인터페이스로 변경하기
abstract class Hero2 {
	public abstract void fly();
}

class Ironman extends Hero {// 미구현된 메소드를 강제로 구현하게 함 (강제성)

	@Override
	public void attack() {// 부모의 미구현 메소드 구현하기
		// 부모는 파라미터가 없는데 자식이 파라미터 있을 수가 없음 (있으면 오류남)
		// public void attack(int number) 이렇게 하면 오류
		System.out.println("");
	}

	@Override
	public void eat() {
	}

	@Override
	public void sleep() {
	}

	@Override
	public void fly() {
		
	}

}

class Hulk extends Hero {

	@Override
	public void attack() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void eat() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void sleep() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		
	}

}

class Spiderman extends Hero {

	@Override
	public void attack() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void eat() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void sleep() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		
	}

}

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

	}
}

 

01. PACKAGE

  • 패키지명.패키지명 = '.'은 폴더 개념
  • ex. net.daum.map → 큰 단위부터 작은 단위 순
  • 관련성 있는 것들끼리 뭉쳐놓은 것
  • 관련성 있는 자바 파일들을 폴더 단위로 구분

 

02. IMPORT

  • 사용하고자 하는 클래스 또는 인터페이스가 다른 패키지에 소속되어 있을 때 사용
  • 패키지 선언과 클래스 선언 사이에 작성
  • 사용하고자 하는 클래스들이 동일한 패키지 소속이라면 *를 이용해서 한번에 표시할 수 있음
  • *은 현재 파일에서 사용하는 것만 가져오는데, 서로 다른 패키지에서 동일한 클래스 이름이 존재할 때는 사용 불가
package inheritance
      
	import java.util.ArrayList;//상위패키지.하위패키지.클래스명;
	import java.util.HashSet;
	import java.util.HashMap;
    
    //위 3개를 *로 묶음
	import java.util.*; 

public class Inheritance {
}

 

03. 접근제어자의 의미

  • API를 사용할 때 제어자에 따라서 접근 허용여부가 달라짐
  • 클래스 및 인터페이스와 멤버의 접근을 제어하기 위해 사용
  • 클래스, 생성자, 메서드, 필드 선언할 때 사용
  • 접근 제어자 크기 순 : public > protected > default > private
  • 클래스 선언에서는 public, default만 사용 가능

 

04. 접근제어자의 종류

01) public

  • 접근 범위가 가장 큰 제어자, 다른 패키지에서 접근 가능

[ 코드 1 ]

package inheritance;

public class Ingeriatnace {
	public int number;
}

[ 코드 2 ]  코드 1에 있는 클래스 호출하기

package access;

public class AccessModifier {
	public static void main(String[] args) {
    	//다른 패키지에 있는 클래스 호출 : 앞에 public 붙어서 불러올 수 있음
        Inheritance i = new Inheritance();
    }
}

02) protected

  • 기본적으로 같은 패키지 내에서는 접근 가능
  • 상속받은 자식 클래스만 다른 클래스에서 접근 가능
  • 자식은 부모의 것을 호출할 수 있음

03) default

  • 제어자를 선언하지 않을 때 자동으로 선언 (생략)
  • 같은 패키지 내에서만 접근 가능
  • 다른 패키지에서 접근 불가
  • 내부에서만 사용할 수 있도록 접근 제한
package inheritance;

class Apple{//앞에 다른 게 안 붙었을 때 default
	
	}

04) private

  • 자신의 클래스에서만 접근 가능
  • 다른 클래스에서 접근 불가
  • getter와 setter 함께 사용함
class Apple{
	
	private int number;//private 접근제어자 생성
	
	public void setNumber(int number) {//setter
		if(number > 100) {
			number = 60;
		}
		this.number = number;
	}
	
	public int getNumber() {//getter
		return this.number;//우회 접근
	}

public class Inheritance {

	public static void main(String[] args) {

		Apple a = Apple.getInstence();

		a.setNumber(150);//사과 넘버에 150 저장
		//private number에 접근하지 못해서 메소드 활용
		System.out.println(a.getNumber());//60 ; 100이상은 값이 60이 나오도록 설정
	}
}

 

05. STATIC ; 정적, 고정, 정적변수

  • 자바에서는 정적 개념과 동적 개념이 있음
  • 정적은 클래스가 로드되는 시점, 동적은 로드된 클래스가 실행된 이후를 의미
  • 객체는 동적 데이터로, 프로그램이 실행된 이후에 발생되는 대표적인 형태
  • 정적 멤버 (static member) :
    클래스를 정의할 때 static  키워드를 사용한 프로퍼티와 메서드는 해당 클래스의 인스턴스를 생성하지 않아도 접근 가능한 것
  • static은 변수가 하나이고 한 개의 값만 가질 수 있음 
package static01;

class Apple {
	static int count;//static이 붙으면 메소드 영역
}

public class Static01 {
	public static void main(String[] args) {
		
		Apple.count = 10;//메소드 영역에서 가져옴
		System.out.println(Apple.count);//10
		
		Apple a1 = new Apple();
		a1.count = 10;
		
		Apple a2 = new Apple();
		a2.count = 100;
		
		System.out.println(a1.count);//100
	}
}
  • static final을 쓰면 값이 고정됨 = 상수 (변경 불가)
package static01;

class Apple {
	static final int COUNT = 100;//=상수 (상수의 변수명은 모두 대문자)
	static final double PI = 3.141592;//고정된 값 사용할 때
}

 

06. 상속

  • 기존의 작성된 클래스 재활용 할 수 있음
  • 클래스 설계 시, 중복되는 멤버를 미리 부모 클래스에 작성해 놓으면, 자식 클래스에선 해당 멤버를 작성하지 않아도 됨
  • 클래스 간의 계층적 관계를 구성함으로써 다형성의 문법적 토대 마련
  • 자바의 모든 클래스는 Object의 하위 클래스 (최상위 부모 : Object)
  • 자바에서 클래스는 단 한 개의 클래스만을 상속받는 단일 상속만 가능
  • 자식은 부모의 코드를 활용 가능하지만 부모는 자신이 없는 자식의 코드 활용 불가능
  • 부모 클래스 = 상위 타입 = 슈퍼 타입 <-> 자식 클래스 = 하위 클래스 = 서브 타입

[ 기본 형식 ]

class Dog extends Animal{//Animal의 상속을 받는 Dog 클래스

}

[ 활용 ]

package inheritance;

class Animal {
	String name;
	int age;	
}

class Dog extends Animal{//부모 : Animal, 자식 : Dog
//Animal 타입을 내려받는 Dog
//하나의 부모만 가능
}

class Cat extends Animal{//부모 : Animal, 자식 : Cat
}

public class De {
	public static void main(String[] args) {
    
		Dog01 dog = new Dog01();
		Cat01 cat = new Cat01();
		
		dog.name = "강아지";
		dog.age = 4;
		cat.name = "고양이";
		cat.age = 2;
        
	}
}

 

07. 오버라이드

  • 상속, 메서드 재정의
  • 부모의 메소드를 자식 클래스에서 재정의해서 사용하는 것
  • 부모의 메소드와 동일한 시그니처(리턴타입, 메서드명, 매개변수)를 가지고 있어야 함
    (만약 다르다면, 다른 메소드로 인식)
  • 접근 제한을 동일하게도 설정 가능하고, 더 확장해서 지정할 수도 있음
    (ex. 부모 : default, 자식 : public으로 설정 가능)
  • 새로운 예외를 Throw 할 수 없음
  • 오버라이드 했다면 상단에 @override라고 표시됨
  • 자식의 메소드를 재정의 했다면 부모의 메서드는 은닉됨
  • 은닉된 부모의 객체를 호출할 때는 super로 호출함
  • 파라미터가 달라지면 오류로 인식해서 오버라이드 되지 않음

[ 활용 1 ]

class Animal {//부모
	String name;
    int age;
    public void sound() {
    	System.out.println("자식마다 소리가 달라요.");//자식이 재정의 했을 때 보여지지 않음
    }
}

class Dog extends Animal {
    @Override// '@' = Annotation 주석으로 소스코드에 추가해서 사용할 수 있는 메타 데이터의 일종
    //부모에 정의된 메소드를 재정의
		public void sound() {
			System.out.println("멍");
		}
}

class Cat extends Animal {
	@Override
		public void sound() {
			System.out.println("야옹");
		}
}

public class Inherit {
	public static void main(String[] args) {.
    	Dog dog = new Dog();
        Cat cat = new Cat();
        
        dog.sound();//멍
        cat.sound();//야옹
        
        //배열에 넣고 출력
        Animal[] oArr = new Animal[2];
        oArr[0] = new Dog();
        oArr[1] = new Cat();
        
        for (int i = 0; i < oArr.length; i++) {
        	oArr[i].sound();
        }
        //멍
        //야옹
	}   
}

[ 활용 2 ]

class Human {
	String name;
    int age;
	public void sound() {
		System.out.println("한국인");
	}
}

class Asia extends Human {//Human 타입을 받는 Asia 클래스 
}

class Korean extends Asia {//Asia 타입을 받는 Korean 클래스 (몇 개를 타고 들어가도 상관없음)
	
    String ssn;//부모타입에는 없고 자식타입에만 있음
	void myInfo() {
		System.out.println("이름은 " + name + "입니다.");
		System.out.println("나이는 " + age + "입니다.");
		System.out.println("주민번호는 " + ssn.substring(0, 8) + "******입니다.");
	}
    
	@Override//Human(부모)에 있는 것을 재정의
	public void sound() {
		System.out.println("사운드");
	}
}

public class Inherit {
	public static void main(String[] args) {
	
		Korean korean = new Korean();
        korean.name = "김자바";
        korean.age = 45;
        korean.ssn = "900131-1234567";
        korean.myInfo();
	}
}
/*
이름은 김자바입니다.
나이는 45입니다.
주민번호는 900131-1******입니다.
*/

[ 활용 3 ]

package inheritance;

import java.util.*;

public class De {
	public static void main(String[] args) {
		
        //Animal이 부모 타입이라서 이렇게 선언 가능
		Animal dog = new Dog();//오버라이드 된 내용으로 'dog'에 들어감
		Animal human = new Human();//오버라이드 된 내용으로 'human'에 들어감
		human.sound();//사람 ;human에 재정의
        human.name();//컴파일 오류 ;부모 타입인 Animal에 name이 없음
        //animal에 있던 것은 오버라이드 되는데 animal에 없는 것은 없는 것처럼 보임
        
		//'name'을 사용하는 방법 = 데이터 타입 변경하기 (다형성)
		//방법 1
		Human hu = (Human) human;
		hu.name = "이름";
        
        //방법 2
		((Human) human).name = "이름";
		
		Object obj = new String();//Object이 최상위 부모이므로 가능
        
		Dog d = new Human();//서로 데이터 타입이 달라서 불가능
		
		List<Integer> l = new ArrayList<>();//ArrayList가 List에 포함되므로 가능
		Set<Integer> s = new HashSet<>();//가능
		Map<Integer, Integer> m = new HashMap<>();//가능
	}
}

class Animal {
	public void sound() {
		System.out.println("달라요");
	}
}

class Human extends Animal {
	String name;//부모에는 없는 변수
	@Override
		public void sound() {
			System.out.println("사람");
		}
}

class Dog extends Animal{
	@Override
		public void sound() {
			System.out.println("멍");
		}
}

08. Polymorphism (다형성)

  • 다양한 형태로 변할 수 있는 것
  • 동적 바인딩으로 런타임 때 최종 타입이 결정되는 것
  • 다형성을 지원하려면 그 언어가 동적 바인딩을 지원해야 함
  • 다형성은 상위 클래스에 만들어진 메소드에 한해 가능

[ 활용 ]

package Polymorphism;

import java.util.HashSet;
import java.util.Set;

class Hero {
	public String name;
	public void attack() {
		System.out.println("기본 공격");
	}
}

class Ironman extends Hero {
	public int suitCount;
	
	@Override
	public void attack() {
		System.out.println("레이저 공격");
	}
	
	public void makeSuit() {
		System.out.println("Javis! 슈트 만들어");
	}
}

class Hulk extends Hero {
	@Override
	public void attack() {
		System.out.println("주먹 공격");
	}
}

class SpiderMan extends Hero {
	@Override
	public void attack() {
		System.out.println("거미줄~~");
	}
}

public class Polymorphism {
	public static void main(String[] args) {
		
		Hero h1;//선언
		h1 = new Ironman();//Ironman을 h1 값으로 대입
		//런타임 때, 반드시 상위 타입이 앞에 와야 함
		
		//히어로로 만들었으면 히어로가 가지고 있는 것만 보여줌
		h1.attack();//레이저 공격
		Ironman ironman = (Ironman) h1;//캐스트
		ironman.makeSuit();//Javis! 슈트 만들어
		
		//같은 주소값이 나옴
		System.out.println(h1);//Polymorphism.Ironman@5e91993f
		System.out.println(ironman);//Polymorphism.Ironman@5e91993f
		
		Hulk hulk = new Hulk();
		SpiderMan man = new SpiderMan();
		ironman.attack();//레이저 공격
		hulk.attack();//주먹 공격
		man.attack();//거미줄~~
		
		//배열 넣어서 for문으로 출력
		Set<Hero> set = new HashSet<Hero>();
		set.add(ironman);
		set.add(hulk);
		set.add(man);
		
		for (Hero hero : set) {
			hero.attack();
		}
		//거미줄~~
		//주먹 공격
		//레이저 공격
	}
}

 

09. 추상화

  • 현실화 되어질 필요가 없는, 인스턴스화할 필요가 없는 성질의 클래스
  • 인터페이스의 역할을 하면서 클래스 같은 돌연변이 클래스
  • 추상은 대략적으로 만들었기 때문에 내부 구성을 완벽히 만들어야 객체 생성 가능
  • 정물은 완벽하게 객체를 만들어서 new만 붙여도 객체 생성 가능
  • 추상은 자신의 인스턴스를 발생시킬 수 없는 형태로 만들어짐
  • 인스턴스화될 필요가 없지만 상속 개념에서 중요한 위치를 갖게 될 때, 추상 클래스로 선언
  • 객체로 만들 목적이 아님

 

10. 추상클래스 선언 규칙

  • 리턴 타입 앞에 abstract라고 붙이고 메소드 괄호 뒤에 ;를 붙여 명령문을 끝냄
  • 클래스에 정의된 메소드 중 추상 메서드가 하나라도 있으면 추상클래스가 되어야 함
  • 추상 메소드가 있다면 클래스 앞에 abstract라고 붙여줘야 함
  • 추상 메소드는 메서드 바디가 없는 형태 ( 중괄호{} 없음 )
  • 자신의 인스턴스를 만들 수 없음
  • 생성자, 메소드, 필드 모두 선언 가능, 상속 가능
  • 추상 메소드가 없지만 클래스를 추상화하고 싶으면 클래스 앞에 abstract를 붙여주면 됨

[ 기본 형태 ]

abstract class Hero{//추상 클래스
	public abstract void attack();//추상 메소드, 바디 없음
}

[ 활용 ]

abstract class Hero{//추상 클래스
	public String name;
	public abstract void attack();
}

class Ironman extends Hero{
//추상클래스를 상속하려면 필수로 추상메소드 사용해야 하거나 추상화 클래스로 만들어야 함
	@Override
	public void attack() {
		System.out.println("부모에서 미완이라면 자식에서 만들어주면 됨.");
        //미완성 메소드를 완성시켜 사용합니다.
	}
	
}

class Hulk extends Hero {
	@Override
	public void attack() {//강제 구현
		System.out.println("강제적으로 만들주기");
	}
}

class SpiderMan extends Hero {
	@Override
	public void attack() {
		//상속은 오버라이드 안 해도 쓸 수 있었다면 추상 클래스는 강제를 줌
		//강제적으로 해당 내용을 구현해야 할 때 사용
		System.out.println("이렇게 추상 클래스가 있으면 나머지 강제로 진행");
	}
}

public class Abstractor {
	public static void main(String[] args) {
		
		Hero h = new Hero(); //컴파일 에러가 나옴
		//= 객체로 만들 수 없음, 인스턴스화 할 수 없음
        
        SpiderMan sp = new SpiderMan();//자식은 가능
		sp.attack();
        //이렇게 추상 클래스가 있으면 나머지 강제로 진행
		
	}
}

 

참고자료
신용권, '혼자 공부하는 자바'
반응형