JAVA _기초

[JAVA] Generic - 상속, 다형성, 추상화, 캐스팅

Journey Jeong 2023. 2. 28. 12:08

제너릭(Generic) 학습 전 이 전 배웠던 클래스 캐스팅(추상화 및 다형성) 에 대해 복습을 먼저 진행한다. 

 

<복습> 

1. 상속

  • 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게하고 기능의 일부분을 변경해야 할 경우 상속받은 자식클래스에서 해당 기능만 다시 수정(정의)하여 사용할 수 있게 하는 것
  • 적은 양의 코드로 새로운 클래스 작성 가능
  • 코드를 공통적으로 관리할 수 있어 코드의 추가 및 변경 용이
  • 자식클래스에서 해당 기능을 다시 수정해 사용할 수 있게 하는 데서 오버라이딩(다형성)이 활용

 

2. 다형성

  • 하나의 변수명, 함수명 등이 상황에 따라 다른 의미로 해석될 수 있는 것
  • 오버라이딩(Overriding): 부모클래스의 메서드와 같은 이름, 매개변수를 재정의 하는 것
  • 오버로딩(Overloading): 같은 이름의 함수를 여러개 정의하고, 매개변수의 타입과 개수를 다르게 하여 매개 변수에 따라 다르게 호출할 수 있게 하는 것

 

3. 추상화

  • 추상화란, 공통된 특징을 묶어 하나의 클래스로 정의하는 것을 말한다.

 

4. 추상클래스

  • 여러 클래스간 비슷한 필드와 메서드를 공통적으로 추출해 만들어진 클래스

 

5. 추상메소드

  • 자식 클래스에서 반드시 오버라이딩해야만 사용할 수 있는 메소드를 의미한다. 자바에서 추상 메소드를 선언하여 사용하는 목적은 추상 메소드가 포함된 클래스를 상속받는 자식 클래스가 반드시 추상 메소드를 구현하도록 하기 위함이다. 
  •  abstract키워드를 메소드 앞에 붙여준다.
  • 추상 메소드는 추상 클래스 안에서 선언만하고, 실질적인 메소드의 추상클래스를 상속받은 일반 자녀클래스에서 진행한다.
  • 추상메소드 뒤에 '{}'가 아닌 ';'을 붙인다.

 

5. 추상클래스 및 인터페이스 

  • 상속 관계: '~는 ~이다.' == (is -a)
  • 포함 관계: '~는 ~을 가지고 있다.' == (has -a)

 

6. 캐스팅 형변환 (클래스의 형변환) 

  • 단순히 한 데이터 타입으로 변환하는데 사용되는 기술
  • 상위 클래스로 변수를 선언하고, 하위클래스의 생성자로 인스턴스 생성
  • 상속관계에서 모든 하위 클래스는 하위 클래스로 형 변환 가능/ 역은 안됨

* 업타운 캐스팅

-> Super타입 클래스: 부모클래스 상속
-> Sup타입 클래스: 부모로부터 상속받은 하위 클래스 
업(Up) 캐스팅: 서브타입의 인스턴스를 수퍼 타입의 변수로 접근하는 것을 말한다. 자식 클래스가 부모 클래스 타입으로 캐스팅 되는것을 뜻한다. (자동 형변환)
- 다운(Down) 캐스팅: 서브타입 인스턴스를 참조하는 수퍼타입 변수를 재참조하는 것을 말한다. 부모 클래스가 자식클래스 타입으로 캐스팅되는 것을 뜻한다. (강제 형변환)

 

https://velog.io/@alicesykim95/OOP-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A52-%EC%B6%94%EC%83%81%ED%99%94-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EB%8B%A4%ED%98%95%EC%84%B1-%EC%93%B0%EB%A0%88%EB%93%9C-%ED%98%95-%EB%B3%80%ED%99%98

 

Java OOP 객체지향(2): 추상화, 인터페이스, 다형성, 쓰레드, 형 변환

📌 1. 추상화(Abstraction) 📎 추상화란? > 추상화란, 공통된 특징을 묶어 하나의 클래스로 정의하는 것을 말한다.예를들어, 람보르기니와 페라리 2대의 차를 보았을때 각 차에는 핸들, 바퀴, 문, 창

velog.io

 

예제 01. 

package casting;

class Person{ //추상화 ->student , employee
	String name; 
	
}
class Student extends Person {
// String name;
}// 학생
class Employee extends Person {
// String name;
}// 회사원 

public class CastiongTest01 {

	public static void main(String[] args) {
		
		// IS-A
		// 사람 > 학생 
		Person p1 = new Student(); //다형성
		Person p2 = new Employee(); //다형성
		// 학생 < 사람		
		Student s1=(Student) p1;
//		Student s2=(Student) p2; -> 강제캐스팅 오류 낼 수 있음
 		

	}

}

예제 02. 

package casting;

public class Person {
	
	String name;
	public Person(String name) {
		this.name =name; 
	}
	public Person() {
	}
	
}
package casting;

public class Employee extends Person{
	int empNo;
	public Employee(String name) {
		super(name); // 슈퍼의 기본생성자 
	}
	public Employee() {
	}
}
package casting;

public class Student extends Person{
	int stdNo;
	public Student(String name, int stdNo) {
		super(name); //항상 첫번째에 위치
		this.stdNo = stdNo;
	}
	public Student() {
	}
}

main>  

 

package casting;

import java.util.ArrayList;
import java.util.Vector;

public class CastingTest02 {

	public static void main(String[] args) {
	
		// 데이터타입에 상관없이 모든 타입 삽입 가능 
		ArrayList list = new ArrayList();
		
		list.add(new Student());
		list.add(new Employee());
		list.add(10); // 아래 캐스팅을 하기에 애매한 부분
		
		/*
		 * for(int i=0; i<list.size(); i++) { 
		 * Person s= (Person) list.get(i);
		 * System.out.println(s.name); 
		 * }
		 */
		
		Vector list2= new Vector();
		//Object obj = new Student("노그린", 1); 
		list2.add(new Student("노그린", 1));
		list2.add(new Student("노블루", 2));
		list2.add(new Student("노레드", 3));
		
		// list 에 동일한 데이터만 저장했더니 출력 시 일괄처리가 가능
		// 그래도 저장할때는 Object에 다형적표현으로 저장되기에, 
		// 읽어올땐 해당하는 객체로 캐스팅 필요 
		for(int i=0; i<list2.size(); i++) {
			Student std=(Student) list2.get(i);// Student에 저장해야함 //데이터 타입에 따라 
			System.out.println(std.stdNo + " : "+ std.name);
		}
		
		
	}

}

예제 02> 

package casting;

import java.util.ArrayList;

public class CastingTest03 {

	public static void main(String[] args) {
		// 마치 배열 처럼 특정한 데이터 타입만 넣는
		// list 선안 시 반영 
		// 제네릭 표현 , 집합에는 스튜던트만 넣을 겁니다. 
		ArrayList<Student> list = new ArrayList<>();
	//	==ArrayList<Student> list = new ArrayList<Student>();
		// Student[] ;
		
		list.add(new Student("홍길동",1));
		list.add(new Student("이길동",2));
		list.add(new Student("삼길동",3));
		// list.add(new Employee("aaa"));
		// list.add(1);
		// 제네릭에 지정한 타입 이외는 허용하지 않습니다.  ---> 컴파일러가 체크 
		
		// 제니릭을 규현해서 데이터를 일괄처리하였더니, 
		// 읽어올때 캐스팅 필요하지 않음 
		for(int i=0; i<list.size(); i++) {
			Student std = list.get(i);
			System.out.println(std.stdNo + "  :  "+std.name);
			
		}
	}

}

 

예제 03>  

package generic;

public class Box {
	
	private Object obj;
	
	public void add(Object obj) {
		obj = obj ;
	}
	public Object get() {
		return obj;
	}
}
package generic;

import casting.Student;

public class BoxTest01 {

	public static void main(String[] args) {
		
		Box box = new Box ();
		box.add(new Student());
		//Object obj = new Student();
		Student std = (Student) box.get();
		System.out.println();
				
		box.add(new String("문자열"));
		// Object obj = new String("문자열"); 
		String str= (String) box.get();
		
	}

}

 

 

1. 제네릭(Generic) 

 

01. 정의:

제네릭(Generic)은 직역하자면 '일반적인'이라는 뜻으로,  '데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법'이다.

 

ArrayList 및 LinkedList 타입 지정할때는 

객체<타입> 객체명 = new 객체<타입>(); 으로  <> 괄호 안에 들어가는 타입을 지정해준다.

 
ArrayList<Integer> list1 = new ArrayList<Integer>();
 
ArrayList<String> list2 = new ArrayList<Integer>();
   
 
LinkedList<Double> list3 = new LinkedList<Double>():
 
LinkedList<Character> list4 = new LinkedList<Character>();

 

이때, 어떤 자료를  String 타입도 지원하고싶고 Integer 타입 등 많은 지원하고 싶을 때 제네릭이라는 것을 사용한다.

--> 즉  제네릭(Generic)은 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것을 의미한다.

한마디로 특정(Specific) 타입을 미리 지정해주는 것이 아닌 필요에 의해 지정할 수 있도록 하는 일반(Generic) 타입이라는 것이다.

 

02. Generic의 장점

 

(1) 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.

(2) 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없다(캐스팅할 필요가 없다). 즉, 관리하기가 편하다.

(3) 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.

 

03. Generic 주요 기능 

(1) 저장 시 컴파일러 타입 체크를 해준다.

(2) read 시 캐스팅이 필요치 않다. 

 

 

예제 01>  

package generic;

public class Box {
	
	private Object obj;
	
	public void add(Object obj) {
		obj = obj ;
	}
	public Object get() {
		return obj;
	}
}
package generic;

import casting.Student;

public class BoxTest01 {

	public static void main(String[] args) {
		
		Box box = new Box ();
		box.add(new Student());
		//Object obj = new Student();
		Student std = (Student) box.get();
		System.out.println();
				
		box.add(new String("문자열"));
		// Object obj = new String("문자열"); 
		String str= (String) box.get();
		
	}

}

 

 

예제 02.

package generic;
// 제네릭 타입
// 클래스 또는 인터페이스 이름 뒤에 <> 안쪽에 타입을 대신하여 타입파라미터 표현 
// 일반적으로 타입파라미터는 대문자 한글자 표기
// 제네릭으로 정의한 클래스 : 현재 T의 데이터 타입은 아직 결정 되지 않았음
public class Case<T /*, V*/ > { // T, V 와 같이 멀티형도 가능 
	
	private T name; 
	public void setName(T name) {
		this.name= name;
	}
	public T getName() {
		return name;
	}
	
	
}
package generic;

public class GenericTest01 {

	public static void main(String[] args) {
		
		Case<String> ca = new Case<>();  // case 클래스의 타입은 String 이 됨 
		// 즉 T = String 
		ca.setName("이름");
		
		ca.getName();
		System.out.println();
		

	}

}

 

'JAVA _기초' 카테고리의 다른 글

[JAVA] 콜렉션(Collection)  (0) 2023.02.27
[JAVA] Inheritance : 상속_03  (0) 2023.02.23
[JAVA] Inheritance : 상속_02  (0) 2023.02.22
[JAVA] Inheritance : 상속 _01  (0) 2023.02.21
[JAVA] Exceptions: 예외  (0) 2023.02.20