기록
  • 0927 13일차
    2023년 09월 27일 16시 35분 09초에 업로드 된 글입니다.
    작성자: 삶은고구마

    0926(어제) 실습과제 1,2,3 복습


    오버로딩,오버라이딩 개념 확인

    둘의 차이점을 다시 한 번 알아둘 것

    오버로딩: 이름이 동일한 메소드명에 리턴타입, 매개변수 등을 다르게 해서 사용하는 방법

    오버라이딩: 상속관계인 상위 클래스의 메소드를 하위클래스가 재정의 해서 사용.

    예를들어 부모 클래스의 printHello()란 메소드에선 "부모"라고 출력한다 할때..

    자식 클래스에서도 부모클래스의 printHello()메소드를 가져다가 "부모"라고 호출 할수도있지만

    재정의 해서 "자식"이라고 출력되도록 수정 가능. 자식마다 출력될 값이 다를 수 있으니까.


    오브젝트-부모클래스-자식클래스-손자클래스

    손자클래스에서는 부모클래스의 필드나 메소드를 사용할 수 있다.(대물림)

    단 , 한 부모 아래 여러 자식 클래스가 있는 경우 자식 클래스끼리는 연관관계가 아님.(별개의 존재)

    부모에게 물려받은 속성의 접근제한자가 protected 와 private일 때 알아보자

    1)protected인 경우

    this.name = name;

    이런식으로 직접 접근 가능

    2)private인 경우

    자식이여도 직접 접근 불가능

    부모 클래스의 getter setter를 이용해서 초기화 

     

    원시형

    int double boolean..   == :값비교

    참조형

    == : 주소값 비교

    equals : 값비교

     

    clone() 사용시 왜 오버라이딩 해야하나? 질문글 다시 보기


    1.다형성(polymorphism)

    예제 animal패키지 

    상속 없이 다형성도 없음

    상속을 이용해 부모타입으로부터 파생된 여러가지 타입의 자식 객체를 부모 클래스 타입 하나로 다룰 수있는 기술

    으아아아악

    2.추상클래스/인터페이스

    예제 animal패키지 : 상속+다형성+추상클래스+인터페이스

    전체 요약 uml


     

    실행 클래스 AnimalMain

    더보기
    package sh.java.polymorphism.animal;
    
    import java.util.Random;
    
    public class AnimalMain {
    
    	public static void main(String[] args) 
    	{
    		// TODO Auto-generated method stub
    		AnimalMain main = new AnimalMain();
    //		main.test1();
    //		main.test2();
    //		main.test3();
    //		main.test4();
    //		main.test5();
    //		main.test6();
    //		main.test7();
    //		main.test8();
    //		main.test9();
    		main.test10();
    	}
    	/**
    	 * Animal 을 상속하고, Flyable인터페이스를 구현한 Eagle 클래스를 작성.
    	 */
    	private void test10()
    	{
    		Animal animal = new Eagle();
    		animal.say();
    		animal.attack();
    		animal.eat("참새");
    		Flyable flyAnimal = (Flyable)animal;
    		flyAnimal.fly();
    		
    	}
    	
    	
    	/**
    	 * 추상클래스는 추상메소드를 구현하지 않고, 자식클래스로 위임할 수 있다.
    	 */
    	private void test9()
    	{
    		Eatable eat1 = new Tiger();
    		Eatable eat2 = new Lion();
    		Eatable eat3 = new Snake();
    		
    		eat1.eat("고기");
    		eat2.eat("얼룩말");
    		eat3.eat("개구리");
    		
    	}
    	
    	
    	
    	
    	/**
    	 * 다형성
    	 * -상속을 이용한 기술
    	 * -자식개체를 부모 타입으로써 제어하는 기술
    	 * 
    	 * 형변환
    	 * -up-casting   부모타입으로 변환 자동으로 일어남
    	 * -down-casting 자식타입으로 변환 명시적으로 변환(직접 작성)
    	 */
    	private void test1()
    	{
    		Lion lion = new Lion();
    		Tiger tiger = new Tiger();
    		
    		
    		//up casting
    		//진짜 객체가 바뀌는건 아니고 바뀐척하는거.
    		Animal animal1 = lion; //Lion ->Animal (업캐스팅)
    		Animal animal2 = tiger;
    		
    		//down casting
    		//Lion lion2 = animal1; //cannot convert from Animal to Lion
    		Lion lion2 = (Lion)animal1;
    		Tiger tiger2 = (Tiger)animal2;
    		//Lion lion3 = (Lion)animal2;//java.lang.ClassCastException 호랑이가 사자로 바뀔수없다 어쩌고
    		//java.lang.ClassCastException:런타임 에러
    		//하지만 컴파일에러는x
    	}	
    	
    	/**
    	 * 해당타입으로 제어 : 모든 기능 사용가능
    	 * 부모타입으로 제어 : 부모클래스에 선언된 기능만 사용 가능
    	 */
    	private void test2()
    	{
    		Lion lion = new Lion();
    		lion.say();//상속받은 메소드
    		lion.kick();//확장한 메소드
    		
    		Animal animal = new Lion();
    		animal.say();
    		//animal.kick(); //lion의 kick 사용 불가 부모타입인 animal의 메소드만 사용가능
    		
    		Lion lion2 = (Lion)animal;
    		lion2.kick(); //부모->자식 다운캐스팅 그제서야 kick을 사용가능
    		((Lion)animal).kick();
    		
    		
    		Animal animal2 = new Tiger();
    		animal2.say();
    		//animal2.punch();//tiger의 punch 사용불가
    		
    		//자식타입으로 다운캐스팅하자
    		Tiger tiger2 = (Tiger)animal2;
    		tiger2.punch(); //부모->자식 다운캐스팅 그제서야 kick을 사용가능
    		((Tiger)animal2).punch();
    	}
    
    	
    	/**
    	 * 다형성 활용1
    	 * -부모타입의 객체배열 사용
    	 */
    	private void test3()
    	{
    		Animal[] animals = new Animal[3];
    		animals[0] = new Lion();
    		animals[1] = new Tiger();
    		animals[2] = new Lion();
    		
    //		for(Animal animal:animals)
    //		{
    //			System.out.println(animal);
    //			animal.say();
    //		}
    		//이 상태에서는 tiger punch나 lion kick을 사용할 수 없다.
    		
    		
    		//instanceof:해당 타입을 확인 true/false을 출력동시에 해당타입으로 형변환 문제없음 보장
    		for(Animal animal:animals)
    		{
    //			//animal instanceof Tiger (객체 instanceof 클래스)			
    //			if(animal instanceof Tiger)
    //				((Tiger)animal).punch();
    //			else if(animal instanceof Lion)
    //				((Lion)animal).kick();
    			
    			//혹은
    			//클래스 객체 비교
    			//1. 객체.getClass()
    			//2. 타입.class
    			if(animal.getClass() == Tiger.class)
    			{
    				((Tiger)animal).punch();
    			}
    			else if(animal.getClass() == Lion.class)
    			{
    				((Lion)animal).kick();
    			}
    		}
    	}
    	
    	/**
    	 * 다형성 활용2
    	 * -매개변수부에서 사용
    	 */
    	private void test4()
    	{
    		action(new Lion()); //만약 action메소드가 한개면 조건부처리하고...action매개변수가 lion이면 해당 action으로감.자기 타입찾아서.
    		action(new Tiger());
    	}
    	
    	//아래의 메소드 오버로딩처럼 처리해도 되지만 다형성으로 , 한개의 메소드로 처리가능
    //	private void action(Lion lion) {
    //		// TODO Auto-generated method stub
    //		
    //	}
    //	private void action(Tiger tiger) {
    //		// TODO Auto-generated method stub
    //		
    //	}
    	
    	//부모타입 매개변수에 자식타입 매개인수
    	private void action(Animal animal) 
    	{
    		// TODO Auto-generated method stub
    		if(animal instanceof Tiger)
    		((Tiger)animal).punch();
    		else if(animal instanceof Lion)
    		((Lion)animal).kick();
    	}
    	
    	
    	/**
    	 * 다형성활용3
    	 * -리턴타입에서 사용하기
    	 */
    	
    	private void test5()
    	{
    		Animal animal1 = generateAnimal();
    		Animal animal2 = generateAnimal();
    		
    		System.out.println(animal1);
    		System.out.println(animal2);
    	}
    
    
    	//만약 반환타입이 Tiger나 Lion이면 에러.부모타입으로 선언해야 tiger,lion둘다 에러없음
    	private Animal generateAnimal()
    	{
    		Random rnd = new Random();
    		//현재 사자,호랑이 두가지니까 boolean 사용
    		if(rnd.nextBoolean())
    		{
    			return new Lion();  //참이면 사자
    		}
    		else
    		{
    			return new Tiger(); //거짓이면 호랑이
    		}
    	}
    	
    	
    	/**
    	 * 정적 바인딩 static 
    	 * -메소드 호출시 해당객체의 타입에 따라 실행 메소드가 결정
    	 * -컴파일 타임에 결정
    	 * ★★★★★동적 바인딩★★★★★
    	 * -전제조건이있음
    	 * -상속,overriding
    	 * -해당객체의 타입이 아닌 실제 객체의 오버라이딩된 메소드 실행
    	 */
    	private void test6()
    	{
    //		//정적바인딩
    //		Lion lion  = new Lion();
    //		lion.kick(); 
    //		lion.say();//여기선 override 된 메소드 나옴 i say 사자 입니다.
    //		//동적바인딩
    //		Animal animal  = lion;
    //		animal.say();//kick은 자식에서만 확장된 메소드라서 쓸수없고 say는쓸수있음
    		
    		
    		Animal[] animals = new Animal[]
    				{generateAnimal(),generateAnimal(),generateAnimal()};
    		
    		for(Animal animal:animals)
    		{
    			animal.say(); //형변환없이 바로 오버라이딩된 say 호출
    			//형변환 없이 확장된 기능(자식에만있는 메소드)을 이용
    			animal.attack(); //형변환없이 바로 오버라이딩된 어택(kick과 punch)
    			//만약 tiger클래스에서 오버라이드된 attack를 주석처리하면 부모클래스의 attack이 실행됨.
    			//그리고 주석처리한다고해서 오류가 나지 않음..단지 tiger만의 attack이 실행이 안됨.
    		}
    	}
    	
    	/**
    	 * 추상클래스/인터페이스
    	 * -추상메소드 구현 강제화 기능
    	 * -특정클래스에 규격(약속)을 제공 (어떤 메소드를 반드시 구현해야한다!)
    	 * -부모타입 제어 시 자동으로 동적바인딩
    	 */
    	private void test7()
    	{
    //		Animal animal  = new Animal();//Cannot instantiate the type Animal
    //		Runnable run = new Runnable();//Cannot instantiate the type Runnable
    		
    		//부모클래스처럼 쓸 수 있음.
    		Runnable run1 = new Tiger();
    		Runnable run2 = new Lion();
    		
    		run1.run();//무조건 구현
    		run2.run();
    		
    		//Runnable타입으로는 Tiger타입의 기능을 사용할 수 없다
    		//run1.say();
    		
    		Tiger tiger =(Tiger)run1;
    		tiger.say();
    		Animal animal  = (Animal)run1;
    		animal.attack();
    		
    		//object형으로도 바꿀 수 있음.
    		Object obj = run1; //업캐스팅
    		//obj.say();//오브젝트형이라 say못함
    	}
    	
    	/**
    	 * 인터페이스도 부모클래스처럼 사용가능!
    	 */
    	public void test8()
    	{
    		Runnable[] rs = {
    				 		new Tiger(),
    				 		new Lion(),
    				 		new Tiger(),
    				 		//new Snake() 규격을 지킨 클래스만 들어올 수있어서 snake는 들어올 수 없다.
    						};
    		for(Runnable r: rs)
    		{
    			r.run();
    		}
    		
    	}
    	
    	
    }

    부모 클래스 Animal

    더보기
    package sh.java.polymorphism.animal;
    
    
    /**
     * 2023-09-27
     * 부모클래스
     * 메소드 구현 강제화
     * -부모클래스의 정의된 메소드를 강제로 override하도록 함.
     * -추상클래스로 또는 인터페이스 작성
     *
     * 1.추상클래스 abstract
     * -미완성 클래스
     * -0개 이상의 추상메소드를 가지고있다.
     * -추상메소드:abstract,메소드 바디x(중괄호 부분없음)
     * -추상클래스의 자식클래스는 부모추상메소드를 반드시 구현해야함.안하면 오류
     * -객체화 할 수 없다. new Animal 이런거 못함
     * -일반클래스이므로 추상메소드 외에도 필드/메소드를 얼마든지 가질 수있다.
     * 
     * 2.인터페이스 interface
     * -추상메소드와 상수만 가질 수 있다.
     * -규격만 정해줬는데 jdk8 이 후에는 default,static메소드를 추가적으로 가질 수 있다.
     * -객체화 못함 
     * -다중 구현 가능 implements a,b,c...
     * -인터페이스간의 구현은 extends 키워드 사용 (상속가능)
     * <blockquote>
     *   public interface A extends B{}
     *
     * 
     * 둘 중 뭘써야하냐..?
     * 자식이 있으면 1번, 아니면 2번
     * 
     * 추상클래스는 인터페이스의 강제 메소드구현을 피할수있음
     */
    public abstract class Animal implements Eatable
    {
    	//강제성을 부여하기
    //	public void attack()
    //	{
    //		System.out.println("공격!!");
    //	}
    	
    //	public void eat(String food)
    //	{
    //		System.out.println(food+"를 먹는다.");
    //	}
    	
    	/**
    	 * 추상메소드
    	 * -반드시 추상클래스 하위에 있어야 한다.
    	 * type Animal can only be defined by an abstract class
    	 */
    	public abstract void attack(); //강제성
    	
    	public void say()//비 강제성
    	{
    		System.out.println("저는 동물입니다.");
    	}
    }

    인터페이스 - Flyable

    package sh.java.polymorphism.animal;
    
    public interface Flyable 
    {
    	void fly();
    	
    }

    인터페이스 - Eatable

    package sh.java.polymorphism.animal;
    
    public interface Eatable {
    	void eat(String food);
    }

    인터페이스 - Runnable

    package sh.java.polymorphism.animal;
    
    
    /**
     * @author user1
     * 2023-09-27
     * 
     * 인터페이스
     * -추상메소드
     * -public static final 상수
     * -default 메소드
     * -static 메소드
     */
    public interface Runnable 
    {	
    	//public static final이 붙음
    	int NUM = 10;
    	//자동으로 public abstract가 붙음
    	void run();
    }

     

    자식클래스 - Lion

    package sh.java.polymorphism.animal;
    
    public class Lion extends Animal implements Runnable //규격
    {
    	public void kick()
    	{
    		System.out.println("Lion kick🦿🦿");
    	}
    	
    	@Override
    	public void say() {
    		System.out.println("i say 사자 입니다.");
    	}
    	
    	@Override
    	public void attack() {
    		// TODO Auto-generated method stub
    		kick();
    		
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		System.out.println("사자가 달린다.");
    	}
    
    	@Override
    	public void eat(String food) {
    		// TODO Auto-generated method stub
    		System.out.println("사자가 "+ food +"를 먹는다.");
    	}
    }

     

    자식클래스 - Tiger

    package sh.java.polymorphism.animal;
    
    public class Tiger extends Animal implements Runnable
    {
    	public void punch()
    	{
    		System.out.println("tiger punch👊👊");
    	}
    
    	@Override
    	public void say() {
    		System.out.println("i say 호랑이 입니다.");
    	}
    
    	//부모클래스인 Animal이 추상클래스가 되면 attack 주석시 오류가 발생.
    	//무조건 오버라이드된 메소드 구현해야한다고.
    	@Override
    	public void attack() {
    		// TODO Auto-generated method stub
    		System.out.println("자식클래스attack");
    		punch();
    		
    	}
    
    	@Override
    	public void run() {
    		// TODO Auto-generated method stub
    		System.out.println("호랑이가 달린다.");
    	}
    
    	@Override
    	public void eat(String food) {
    		// TODO Auto-generated method stub
    		System.out.println("호랑이가 "+ food +"를 먹는다.");
    	}
    	
    }

     

    자식클래스 - Snake

    package sh.java.polymorphism.animal;
    
    public class Snake extends Animal{
    
    	@Override
    	public void attack() {
    		// TODO Auto-generated method stub
    		System.out.println("뱀이 공격한다🐍");
    //		System.out.println("뱀이 공격한다🐍🐍🐍🐍");?
    	}
    
    	@Override
    	public void eat(String food) {
    		// TODO Auto-generated method stub
    		System.out.println("뱀이 "+ food +"를 먹는다.");
    	}
    }

     

    자식클래스 - Eagle

    package sh.java.polymorphism.animal;
    
    public class Eagle extends Animal implements Flyable{
    
    	@Override
    	public void eat(String food) {
    		// TODO Auto-generated method stub
    		System.out.println("독수리가 "+food+"를 먹고있습니다.🦅");
    	}
    
    	@Override
    	public void fly() 
    	{
    		// TODO Auto-generated method stub
    		System.out.println("독수리가 날고있다.🦅");
    	}
    
    	@Override
    	public void attack() {
    		// TODO Auto-generated method stub
    		snatch();
    	}
    	
    	public void snatch()
    	{
    		System.out.println("독수리가 발톱으로 낚아챘다.🦅");
    	}
    	
    	@Override
    	public void say() {
    		System.out.println("저는 독수리 입니다.🦅");
    	}
    	
    	
    }

    '공부' 카테고리의 다른 글

    1006(16일차)  (0) 2023.10.06
    1005(15일차)  (0) 2023.10.05
    1004 14일차  (2) 2023.10.04
    0926 12일차  (0) 2023.09.26
    0925 11일차  (0) 2023.09.25
    댓글