본문 바로가기
Backend

06월 03일 월 | OOP 13 - JAVA의 상속(super, sub)과 Method Override

by 구라미 2019. 6. 3.

프로그래밍 언어활용 (160시간)

수행평가: 06/14 (4지택일/단답형)

10. 객체지향 프로그래밍 Ⅱ

상속

객체지향 프로그래밍에 대한 것은 IT회사에서 기술면접 때 자주 나온다. 

프로젝트 만들 때 핵심 카테고리 잘 잡기.

클래스의 재활용을 위해서 사용하는 기능.

 

상속이 있을 때

부모와 자식이라는 개념이 나온다.

 

부모,조상 - super class

자식,파생 - sub class

 

클래스간 상속은 다중 상속이 X

▶ 풀이

extends 다음 ,(콤마)로 여러 부모를 추가 할 수 없다는 이야기 이다.

Java에서는 다중상속이 불가하지만 C에서는 가능하다고 한다.

 

 

protected void zero

private void zero

 

상속의 형식

class 자식 extends 부모클래스명 {}

 

package oop0603;

//class앞에 final을 붙였더니 제대로 실행되지 않았다.
//final 클래스는 상속될 수 없기 때문이다.
class AA {
	protected void zero(){}
	public void one(){
		System.out.println("one()...");
	}
	public void two(){
		System.out.println("two()...");
	}
}//class end

class BB extends AA {
	public void three(){
		System.out.println("three()...");
	}
}

class CC extends BB {
	public void four(){
		System.out.println("four()...");
	}
}

class DD {
	public void five(){
		System.out.println("five()...");
	}
	
	public void six(){
		System.out.println("six()...");
	}
}

//class EE extends AA,DD (){클래스는 단일상속만 가능하다. 다중상속이 불가하다.
//	
//}

public class Test01_Sangsok {

	public static void main(String[] args) {
		//상속
		//기존에 있는 것 재활용.
		
		AA aa = new AA();
		aa.one();
		aa.two();
		aa.zero(); //private 속성은 클래스 내부에서만 접근가능하다.
		
		System.out.println("--------------------------------");
		
		BB bb = new BB();
		bb.three();
		bb.one(); //AA에서 상속받은 one 출력가능
		bb.two(); //AA에서 상속받은 two 출력가능
		//bb.zero(); private 속성은 상속되지 않는다.
		
		System.out.println("--------------------------------");
		
		CC cc = new CC();
		cc.one(); 
		cc.two();
		cc.three();
		cc.four();
		
	}//main end
}//class end

위와 같이 클래스 상속은 단일상속만 가능하고 다중상속은 불가하다.

▶ 풀이

예) aa.zero();  zero(); 라는 메소드를 부른 것. (); 는 메소드

여기서는 syso ~ 출력문이 담긴 메소드를 부른 것이다.

 

 

Method Override

Method Override는 함수의 재정의이다.

상속관계에서 메소드를 다시 수정 (상속받은 것을 내 상황에 고쳐쓸 수도 있다. 그런 것을 리폼이라고 한다. )

메소드 오버라이드는 객체지향 프로그래밍에서 서브클래스(자식클래스)가

자신의 슈퍼클래스(부모,조상클래스)들 중 하나에 의해 이미 제공된 메소드를

특정한 형태로 구현하는 것을 제공하는 언어의 특징이다.

 

상속관계에 있는 부모클래스에서 이미 정의된 메소드를 자식클래스에서

같은 시그니쳐를 갖는 메소드로 다시 정의 하는 것이다. 

자바에서 자식클래스는 부모클래스의 private멤버를 제외한 모든 메소드를 상속받는다.

 

오버라이딩의 조건
자바에서 메소드를 오버라이딩하기 위한 조건은 다음과 같다.   

1. 오버라이딩이란 메소드의 동작만을 재정의하는 것이므로, 메소드의 선언부는 기존 메소드와 완전히 같아야한다.
    하지만 메소드의 반환 타입은 부모 클래스의 반환 타입으로 타입 변환할 수 있는 타입이라면 변경할 수 있다.
2. 부모 클래스의 메소드보다 접근 제어자를 더 좁은 범위로 변경할 수 없다.
3. 부모 클래스의 메소드보다 더 큰 범위의 예외를 선언할 수 없습니다.

 

Method Overload는 함수명 중복.

▶ 풀이

오버로드는 같은 메소드명을 써도 매개변수로 다른 메소드를 만들어 구분하는 것.

오버라이드는 재정의.

 

상속과 접근제어자

package oop0603;

class Korea { //모든 클래스는 Object클래스를 상속받아야 한다.
			  //extends Object는 생략가능하다.
	String name = "대한민국"; //앞에 없는것 package가 생략, 같은 package에서 접근가능
	private String name01 = "대한민국"; //private 상속불가
	protected String name02 = "대한민국"; //protected 상속가능. 다른 패키지에서도 접근가능.
	public String name03 = "대한민국"; //public 상속가능. basicJava프로젝트 내에서 모두 접근가능.
	
	//대개 field 변수를 private으로 은폐함
	
	final void view(){}
	void disp(){
		System.out.println(this.name);
	}	
}//class end

class Seoul extends Korea {
	
	
}//class end

public class Test02_Override {

	public static void main(String[] args) {
		// Method Override 함수의 재정의
		// -> 상속관계에서 메소드를 다시 수정하는 것이다.
		
		Korea ko = new Korea(); //ko라는 참조형변수가 주소를 갖고 있다.
		
		System.out.println(ko.name);
		ko.view();
		ko.disp();	
		
	}//main end
}//class end

▶ 풀이

접근제한자에 대해 잘 알아두어야한다.

Korea 라는 클래스(사용자가 만든 자료형) ko (변수)

 

자바 캡슐화(은폐),

Object 클래스는 자바의 핵심이다.

자바의 모든 클래스는 Object 클래스를 상속받는다.

그래서 .을 쳤을 때 여러 메소드들이 뜨는 것.

자바의 기본패키지 java.lang

자바의 최고 조상클래스 Object클래스

자바의 모든 클래스는 생성할 때 무조건 Object클래스를 상속받는다. //자바의 모든 클래스는 Object클래스의 자손이다.

 

class Seoul extends Korea {
	String name = "서울특별시"; //고쳐쓰기 = 오버라이드 , 변수함수를 다시 선언하면 된다.
	@Override //ctrl + space로 오버라이드 불러옴. @ <- annotation 명령어.
	void disp() {
		// TODO Auto-generated method stub
		super.disp();
	}
	
	//final class는 상속불가, final method는 더 이상 오버라이드 할 수 없다.
	
}//class end

@Override <- 재정의하라는 annotation 명령어.

 

 

toString() 오버라이드

package oop0603;

class Jeju extends Object{

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "제주특별자치도";
	}
}

public class Test02_Override {

	public static void main(String[] args) {
		//toString() 오버라이드 후
		Jeju je = new Jeju();
		System.out.println(je.toString());
		System.out.println(je);//toString 생략가능
        
	}//main end
}//class end

//결과값
//제주특별자치도

//toString() 메소드명 생략가능.

toString은 오류잡아낼 때 많이 쓴다.

메모리에 어떤 값이 저장되어있는지 항상 출력해서 확인해보기.

▶ 풀이

프로그래머스에도 있는 내용이다. 자바 중급 - 오버라이드

부모에 있는 서울특별시에다가

리턴값을 "제주특별자치도" 라고 오버라이드 했다.

 

package oop0603;

class Korea { //모든 클래스는 Object클래스를 상속받아야 한다.
			  //extends Object는 생략가능하다.
	String name = "대한민국"; //앞에 없는것 package가 생략, 같은 package에서 접근가능
	private String name01 = "대한민국"; //private 상속불가
	protected String name02 = "대한민국"; //protected 상속가능. 다른 패키지에서도 접근가능.
	public String name03 = "대한민국"; //public 상속가능. basicJava프로젝트 내에서 모두 접근가능.
	
	//대개 field 변수를 private으로 은폐함
	
	final void view(){
		System.out.println("view()...");
	}
	
	void disp(){
		System.out.println("Korea..."+this.name);
	}	
}//class end

class Busan extends Korea {
	String name = "부산광역시";

	@Override
	void disp() {
		System.out.println("Busan..."+this.name);
	}
	
	
	
}//class end

class Jeju {

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "제주특별자치도";
	}
}//class end

class Suwon {
	private String id = "webmaster"; //private 내부접근만 가능
	private String pw = "1234";
	
	@Override
	public String toString() {
		return "Suwon [id = " +id+".pw="+pw+"]";
	}
	
}//class end


class Incheon extends Object {
	private String id = "soldesk";
	private String pw = "5678";
	
	@Override
	public String toString() {
		return "Incheon [id=" + id + ", pw=" + pw + "]";
	}
	
}//class end



class Seoul extends Korea {
	String name = "서울특별시"; //고쳐쓰기 = 오버라이드 , 변수함수를 다시 선언하면 된다.
	@Override //ctrl + space로 오버라이드 불러옴.
	void disp() {
		// TODO Auto-generated method stub
		super.disp();
		System.out.println("Seoul..."+this.name);
	}
	
	//final method는 더 이상 오버라이드 할 수 없다.
	
}//class end


public class Test02_Override {

	public static void main(String[] args) {
		// Method Override 함수의 재정의
		// -> 상속관계에서 메소드를 다시 수정하는 것이다.
		
		Korea ko = new Korea(); //ko라는 참조형변수가 주소를 갖고 있다.
		
/*		System.out.println(ko.name);
		ko.view();
		ko.disp();	*/
		
		//오버라이드 하기 전
/*		Seoul se = new Seoul();
		System.out.println(se.name);
		se.view();
		se.disp();*/
		
/*		//오버라이드 한 후
		Seoul se = new Seoul();
		System.out.println(se.name); //서울특별시
		se.view();
		se.disp(); //Seoul...서울특별시
		
		
		Busan bu =  new Busan();
		System.out.println(bu.name);
		bu.view();
		bu.disp();
		//toString 오버라이드 하기 전
		//oop0603.Busan@15db9742
		System.out.println(bu.toString());*/
		
		//------------------------------------------------
		
		//toString() 오버라이드 후
		Jeju je = new Jeju();
		System.out.println(je.toString());
					
		//------------------------------------------------
		//toString()은 private 변수값을
		//-> 리턴하는 용도로 주로 사용한다.
		Suwon su = new Suwon();
		System.out.println(su.toString());
		System.out.println(su);
		
		//------------------------------------------------
		Incheon in = new Incheon();
		System.out.println(in.toString());
		System.out.println(in);			
		
		
	}//main end
}//class end

private String이 어떻게 오버라이드되는 가에 대한 예제였다.

결과값은

제주특별자치도
Suwon [id = webmaster.pw=1234]
Suwon [id = webmaster.pw=1234]
Incheon [id=soldesk, pw=5678]
Incheon [id=soldesk, pw=5678]

 

 

toString() 자동추가

 

source -> Generate toString()...

교재 읽어보면서 이해해보기.

 


 

Null

Null은 값의 부재, 값이 존재하지 않는 것이다.

-> 레퍼런스 변수를 선언만 해 놓은 상태.

true 참, false 거짓

String str = null; //빈 값
String name = ""; //빈 문자열
System.out.println(str.length()); //0
		
Integer inte1 = null; //빈 값
Integer inte2 = new Integer(0); //0이라는 것을 할당.

//System.out.println(inte1);
System.out.println(inte2.toString()); //Integer클래스도 조상이 Object클래스이다.
System.out.println(inte2);

//결과값
//inte1 : null
//inte2.toString() : 0
//inte2 : 0

 

Integer 클래스는 final클래스이다.

 

메소드 호출방식

메소드 호출방식은 여러가지가 있다.

 

Call By Value *값으로 부르기

Call By Reference *참조로 부르기

 

package oop0603;

public class Test04_CallBy {
	
	public static void test1 (int a, int b){}
	
	public static void test2 (int[] su){} //배열이므로 주소가 넘어가는 것.
	
	public static void test3 (Integer a){} //클래스
	

	public static void main(String[] args) {
		//메소드 호출 방식
		
		int [] su = {10, 15, 20};
		
		//값에 의한 호출방식
		//Call By Value
		test1(su[0],su[2]); // 10 20 
		
		//참에 의한 호출방식
		//Call By References
		test2(su);
		test3(new Integer(50));
				

	}//main end
}//class end

기본형

기본형 메모리 할당

레퍼런스 클래스

 

함수명 작성 시 고려사항.

-> is~~~ //대부분 리턴형이 boolean

-> to~~~

-> get~~~ //가져온다. 거의 리턴값 존재

-> set~~~ //준다. 리턴값 없는 경향있음.

 

 


 

GregorianCalendar

우리가 자주 사용하는 태양력 달력 클래스.

util 패키지 안에 들어있다.

조상: Object 클래스

부모: Calendar 클래스

 

Calendar 클래스의 단점

1. Calendar 인스턴스는 불변 객체(immutable object)가 아니라서 값이 수정될 수 있습니다.

2. 윤초(leap second)와 같은 특별한 상황을 고려하지 않습니다.

3. Calendar 클래스에서는 월(month)을 나타낼 때 1월부터 12월을 0부터 11까지로 표현해야 하는 불편함이 있습니다.

-출처 tcpschool

 

package oop0603;

import java.util.Calendar;
import java.util.GregorianCalendar;

public class Test05_GregorianCalendar {

	public static void main(String[] args) {
		//날짜 관련 GregorianCalendar 클래스
		GregorianCalendar now = new GregorianCalendar();
		System.out.println(now.get(Calendar.YEAR)); //2019
		System.out.println(now.get(Calendar.MONTH)); //+1 이 맞는 월
		System.out.println(now.get(Calendar.DATE)); //3
		
		int crntYear = now.get(Calendar.YEAR);
		System.out.println(now.isLeapYear(crntYear)); //2019년은 윤년아니다.
		System.out.println(now.isLeapYear(2020)); //2020년은 윤년이다.
		
	}//main end
}//class end

 

GregorianCalendar의 add메소드 

은근히 유용한 메소드

많이 사용되는 메소드이다.

▶ 풀이

Calendar클래스는 불변객체가 아니기 때문에 메소드로 값을 새로 쓸 수 있다.

package oop0603;

import java.util.Calendar;
import java.util.GregorianCalendar;

public class Test05_GregorianCalendar {

	public static void main(String[] args) {
	//날짜 관련 GregorianCalendar 클래스
		GregorianCalendar now = new GregorianCalendar();

		//날짜 데이터의 연산
		now.add(Calendar.YEAR, 3); //현재 now날짜에 3년 더하기. // 2022-5-3
		System.out.println(now.get(Calendar.YEAR)); //2022년
		
		//now날짜에 2달 빼기
		now.add(Calendar.MONTH, -2);
		System.out.println(now.get(Calendar.MONTH)); //5 - 2 = 3
		
		//now날짜에 10일 더하기
		now.add(Calendar.DATE, 10);
		System.out.println(now.get(Calendar.DATE));
		
		//연습문제 1)
		//2019년 05월 29일 ~ 2019년 6월 2일
		//총 날수를 구하시오.
		
		//현재 시스템의 날짜 가져오기.
		Calendar start = Calendar.getInstance();
		
		//start의 날짜값을 변경
		start.set(2019, 4, 29);
		start.set(2019, Calendar.MAY, 29);
		
		Calendar end = Calendar.getInstance();
		end.set(2019, Calendar.JUNE, 2);
		
		
	}//main end
}//class end

 

날짜데이터 예제

연습문제 1) 2019년 05월 29일 ~ 2019년 6월 2일
//총 날수를 구하시오.

//연습문제 1) 2019년 05월 29일 ~ 2019년 6월 2일
//총 날수를 구하시오.
		
//현재 시스템의 날짜 가져오기.
Calendar start = Calendar.getInstance();
		
//start의 날짜값을 변경
//2019-05-29
start.set(2019, 4, 29);
start.set(2019, Calendar.MAY, 29);
		
//2019-06-02
Calendar end = Calendar.getInstance();
end.set(2019, Calendar.JUNE, 2);

//1) 2019-6-2 ~ 2019-5-29 = 4
	int cnt1 = 0;
//2) 2019-6-2 ~ 2019-5-29 총 날수 = 5
	int cnt2 = 1;
while(start.before(end)){
	System.out.println(start.get(Calendar.YEAR)+"-");
	System.out.println("-");
	System.out.println(start.get(Calendar.MONTH)+1);
	System.out.println("-");
	System.out.println(start.get(Calendar.DATE));
	System.out.println();
	start.add(Calendar.DATE, 1);
	cnt1 = cnt1+1;
	cnt2 = cnt2+1;
}//while end
System.out.println(cnt1);
System.out.println(cnt2);

//4
//5

□ 이  .before ◇◇의 전날인가

while ("2019-5-29" .before("2019-6-2") 참 

while ("2019-5-30" .before("2019-6-2") 

while ("2019-5-31" .before("2019-6-2") 

while ("2019-6-1" .before("2019-6-2") 

while ("2019-6-2" .before("2019-6-2") 같으므로 거짓 

 

클래스 상속관계에서의 생성자 호출 순서

부모생성자() -> 자식생성자() 순서대로 호출된다.

package oop0603;

class Fruit {
	public Fruit(){
		System.out.println("Fruit()...");
	}
	
}//class end

class Apple extends Fruit {
	public Apple(){
		System.out.println("Apple()...");
	}
}//class end


class PineApple extends Apple {
	public PineApple() {
		System.out.println("PineApple()...");
	} 
}//class end


public class Test06_Constructor {
	public static void main(String[] args) {
		//클래스 상속관계에서의 생성자 호출 순서
		//부모생성자() -> 자신의 생성자() 호출된다. 
		
		//Fruit() -> Apple()
		Apple ap = new Apple();
		
		//Fruit() -> Apple() -> PineApple()
		PineApple pa = new PineApple();
		
	}//main end
}//class end

 

 

 

 

 

 

 

 

 

 

댓글