클래스(배열,업캐스팅,다운캐스팅,instanceof,싱글톤)

최동민·2022년 5월 22일
0

JAVA

목록 보기
4/13

클래스 배열

객체를 여러개 선언해야 하는 경우
배열 타입으로 한번에 선언 후 사용한다.

클래스 배열은 몇차원 배열일까? 2차원 배열
객체는 field의 주소값을 가지고 있다.
그 주소값을 가지고 있는 객체를 담는 배열이다

클래스 배열 선언

  1. 클래스명[] 배열명 = new 클래스명[길이];
  2. 클래스명[] 배열명 =
    new 클래스명(),
    new 클래스명(),

클래스 배열 사용

배열명[index].필드명
배열명[index].메서드명()

배열 예제

package extend;

import java.util.Scanner;

class Animal{
		String name;
		int age;
		String feed;
		
		public Animal() {
		}
		
		public Animal(String name, int age, String feed) {
			this.name = name;
			this.age = age;
			this.feed = feed;
		}

		@Override // 정보를 담을 것 
		public String toString() {
			// TODO Auto-generated method stub
			return "이름 : " + name + "\n나이 : " + age + "살\n먹이 : "
					+ feed;
		}
		
		
	}
	
	public class ArInstance {
		
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Animal[] arAni = new Animal[3];
		
		
		for(int i = 0; i < arAni.length; i++) {
			arAni[i] = new Animal();
			
			System.out.println(i + 1 + "번 동물 이름 : ");
			arAni[i].name=sc.next(); // 문자열
			System.out.println(arAni[i].name + " 나이 : ");
			arAni[i].age = sc.nextInt();
			System.out.println(arAni[i].name + " 먹이 : ");
			arAni[i].feed = sc.next();
		}
		
		for (int i = 0; i < arAni.length; i++) {
			System.out.println(arAni[i]);
		}
		
	}

}

다른 방법

public class ArInstace {
		
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		Animal[] arAni = new Animal[3];
		String name = "";
		int age = 0;
		String feed = "";
		
		for(int i = 0; i < arAni.length; i++) {
			
			System.out.println(i + 1 + "번 동물 이름 : ");
			name = sc.next();
	
			System.out.println(" 나이 : ");
			age = sc.nextInt();
	
			System.out.println(" 먹이 : ");
			feed = sc.next();
			arAni[i] = new Animal(name, age, feed);
		}
		
		for (int i = 0; i < arAni.length; i++) {
			System.out.println(arAni[i]);
		}
		
	}

타입캐스팅이란 형을 변환하는 것.

업캐스팅(up casting)

부모 클래스명 객체 = new 자식생성자();
부모와 자식간의 공통 요소(재정의 메서드)만 사용 가능하며,
자식 클래스의 추가된 것들은 사용할 수 없다.
부모 타입으로 선언되었기 때문에 부모의 필드만 사용 가능하지만
자식 클래스에서 부모 메서드 내용을 재정의 했다면 재정의 된 메서드로 사용된다.

서브 클래스는 슈퍼 클래스의 모든 특성을 상속받는다. 따라서 서브 클래스는 슈퍼 클래스가 될 수 있다.

즉, 서브 클래스가 슈퍼 클래스가 되는 것을 업 캐스팅이라고 한다.

다운캐스팅(down casting)

자식 클래스 타입으로 부모 생성자를 호출하는 오류
부모의 범위가 더 크기 때문에 자식에 담을 수 없다.

서브 클래스가 슈퍼 클래스로 변했을 때 서브 클래스의 인스턴스는 잠시 가려져 있을 뿐 사라지지 않는다.

서브 클래스의 원래 특성으로 돌려놓는 게 다운 캐스팅이다. 

다운 캐스팅은 업 캐스팅과 달리 명시적으로 타입을 지정해야 한다.

instanceof

각각의 타입을 확인할 때 사용하는 문법
값 instanceof 클래스타입 : 값이 클래스 타입이니?
참 또는 거짓의 결과

자식이 부모클래스 특성을 상속받아 부모 클래스 멤버에 접근가능하게 하는 것이 업캐스팅, 이 때 부모클래스 멤버만 사용가능. 자식클래스의 멤버 사용X. 사용을 원하면 명시적 형변환을 해주어야 자식클래스의 멤버도 사용이 가능 즉 부모클래스로 형 변환된 자식 클래스를 원래 자료형으로 형 변환해주어야 한다는 것. 이것이 다운캐스팅.

다운캐스팅을 하기 전에 부모 클래스로 형 변환된 인스턴스의 원래 자료형을 확인해야 변환할 때 오류를 막을 수 있다. 이를 확인하는 예약어가 바로 instanceof 이다.

instanceof 예약어는 왼쪽에 있는 변수의 원래 인스턴스형이 오른쪽 클래스 자료형인가를 확인한다. 

아래 예시를 살펴보자.

package casting;

class Car {

	String brand;
	String color;
	int price;
	
	
	
	public Car() {
	}

	public Car(String brand, String color, int price) {
		this.brand = brand;
		this.color = color;
		this.price = price;
	}	
	
	void engineStart() {
		System.out.println("열쇠로 시동 킴");
	}
	
	void engineStop() {
		System.out.println("열쇠로 시동 끔");
	}
}

class SuperCar extends Car {
	
	String mode;
	
	public SuperCar() {
		
	}

	public SuperCar(String brand, String color, int price, String mode) {
		super(brand, color, price);
		this.mode = mode;
	}
	
	void changeMode(String newMode) {
		this.mode = newMode;
		System.out.println("모드가 바뀌었습니다.");
	}
	
	@Override
	void engineStart() {
		System.out.println("음성으로 시동 킴");
	}
	
	@Override
	void engineStop() {
		System.out.println("음성으로 시동 끔");
	}
	
}

public class CatingTest {
	public static void main(String[] args) {
		//up casting
//		부모 클래스 타입으로 자식 생성자를 호출하는 것
		Car noOptionFerrari = new SuperCar();
//		noOptionFerrari.engineStart(); // 자식클래스에서 재정의 한 메소드 내용으로 출력
//		noOptionFerrari.changeMode();  // 자식 클래스 필드 사용 불가능
		
		//down casting
//		SuperCar brokenCar = new Car(); // 불가능
//		SuperCar brokenCar = (SuperCar) new Car(); // 강제 형변환
//		brokenCar.changeMode("스포츠"); // 하지만 오류 
//		Car클래스는 SuperCar로 형변환 할 수 없음. 
		
		Car car = new Car();
		SuperCar ferrari = new SuperCar();
		
		// 그 객체가 Car 타입이니? 
		if(car instanceof Car) { 
			System.out.println("nice casting"); // 참 
		} else {
			System.out.println("err : wrong casting");  
		}
		
		// 페라리가 Car 타입이니? 
		if(ferrari instanceof Car) {
			System.out.println("nice casting"); // 참 
		} else {
			System.out.println("err : wrong casting"); 			
		}
		
		// car가 SuperCar 타입일까? 땡. 범위를 벗어났다. 
		if(car instanceof SuperCar) {
			System.out.println("nice casting"); 
		} else {
			System.out.println("err : wrong casting"); // 거짓 
		}
		
		// 타입은 Car타입이지만 SuperCar 자식 생성자가 들어가있다면?
		// 내가 업캐스팅을 해도 타입만 맞다면 전부 Car 타입이다. 
		if(noOptionFerrari instanceof Car) {
			System.out.println("nice casting"); // 참 
		} else {
			System.out.println("err : wrong casting"); 
		}
		
	}
}

싱글톤 패턴(Singleton pattern)

객체가 단 1개만 존재할 때 외부에서 new를 하지 못하게 막아주고 클래스 내부에서 new를 한 후 외부에서 선언이 아닌 사용만 해준다.

다른 패키지에서 아이언맨 이라는 클래스를 만들었다.

package single;

public class IronMan {
	
	private IronMan() {}
	
	public static IronMan getInstance() {
		
		IronMan im = new IronMan();
		return im;
	}

	public static void fight() {
		System.out.println("빔 발사");
	}
	
	public void walk() {
		System.out.println("날아간다");
	}

}

클래스 내부에서 new를 한 getInstance();를 불렀고, 선언이 아닌 사용만 해준다. walk();의 사용이 가능해짐.

package single;

public class Stadium {

	public static void main(String[] args) {
//		IronMan i = new IronMan(); // 불가
		// IronMan이 private이기 때문에 접근 X 
		IronMan i = IronMan.getInstance();
		IronMan.fight();
		i.walk();
	}

}
profile
코드를 두드리면 문이 열린다

0개의 댓글