[필기정리]Day13 - final, 상속

SW/Java

2020. 6. 26. 18:17

# final

- final + class는 더 이상 상속을 허용하지 않음이라는 의미

 

// Tip : c에서는 const로 상수를 표시한다

 

- final class의 예시 : Object 클래스의 wait ,notify, notifyall 메소드 등이 있으며,  

                           String 클래스가 대표적인 final 클래스의 예시이다.

 

ex)

final class AAA 
{
}

class BBB extends AAA //에러 발생 
{
}

 

- 메소드에 final이 있으면 메소드 오버라이딩을 허용하지 않는다.

  상속 받은 클래스에서 재정의 불가하다.

 

ex)

class CCC
{
	public final void printHi() //메소드 오버라이딩을 허용하지 않는다. 재정의 불가
	{
	}
}

class DDD extends CCC
{
	public void printHi() // 에러 발생
	{
	}
}    

 

모든 클래스의 최상위 클래스는 Object 클래스이다!

ex)

class EEE
{
	public String toString()
	{
		return "EEE";
	}
}

public EMain
{
	public static void main(String[] args)
	{
		EEE eee = new EEE();
  		System.out.println(eee); //println(Object dbj)[eee.toString();
    }
class FFF extends Object //Object가 생략되어 있다고 생각하면 된다.
{
}

 

가장 최상위의 클래스이기 때문에 오브젝트 클래스는 어떤 클래스의 객체 주소값도 참조할 수 있다.

ex)

class GGG extends Object 
{
}

class HHH extends GGG
{
}

Object obj = new HHH(); // 가능

 

Q. 다음을 프로그램 하시오.

 

Friend 클래스

이름

전화번호

주소

 

메소드

showData : 모든 데이터(전체 제이터)를 출력하는 메소드

showBasicInfo : 기본 데이터(일부 데이터)를 출력하는 메소드

 

HighFriend 클래스 (Friend 클래스 상속)

직장

 

메소드

showData : 모든 데이터(전체 제이터)를 출력하는 메소드

showBasicInfo 메소드에서 이름, 전화번호, 직장을 출력

 

UnivFriend 클래스 (Friend 클래스 상속)

전공

 

메소드

showData : 모든 데이터(전체 제이터)를 출력하는 메소드

showBasicInfo 메소드에서 이름과 전공학과를 출력

 

*** 메뉴 선택 ***

1. 고교 정보 저장

2. 대학 친구 저장

3. 전체 정보 출력

4. 전체 기본 정보 출력

5. 프로그램 종료

선택>>

 

A. 강사님의 답

import java.util.Scanner;

class Friend 
{
	String name;
	String phoneNum;
	String addr;
	
	public Friend(String name, String phone, String addr)
	{
		this.name=name;
		this.phoneNum=phone;
		this.addr=addr;
	}
	public void showData()
	{
		System.out.println("이름 : "+name);
		System.out.println("전화 : "+phoneNum);
		System.out.println("주소 : "+addr);
	}
	public void showBasicInfo(){}
}

class HighFriend extends Friend		// 고교동창
{
	String work;
	
	public HighFriend(String name, String phone, String addr, String job)
	{
		super(name, phone, addr);
		work=job;		
	}
	public void showData()
	{
		super.showData();
		System.out.println("직업 : "+work);
	}
	public void showBasicInfo()
	{
		System.out.println("이름 : "+name);
		System.out.println("전화 : "+phoneNum);
	}
}

class UnivFriend extends Friend 	// 대학동기
{
	String major;		// 전공학과
	public UnivFriend(String name, String phone, String addr, String major)
	{
		super(name, phone, addr);
		this.major=major;
	}
	public void showData()
	{
		super.showData();
		System.out.println("전공 : "+major);
	}
	public void showBasicInfo()
	{
		System.out.println("이름 : "+name);
		System.out.println("전화 : "+phoneNum);
		System.out.println("전공 : "+major);
	}
}

class FriendInfoHandler
{
	private Friend[] myFriends;
	private int numOfFriends;
	
	public FriendInfoHandler(int num)
	{
		myFriends=new Friend[num];
		numOfFriends=0;
	}
	
	private void addFriendInfo(Friend fren)
	{
		myFriends[numOfFriends++]=fren;
	}
	
	public void addFriend(int choice)
	{
		String name, phoneNum, addr, job, major;
		
		Scanner sc=new Scanner(System.in);		
		System.out.print("이름 : "); name=sc.nextLine();
		System.out.print("전화 : "); phoneNum=sc.nextLine();
		System.out.print("주소 : "); addr=sc.nextLine();
		
		if(choice==1)
		{
			System.out.print("직업 : "); job=sc.nextLine();
			addFriendInfo(new HighFriend(name, phoneNum, addr, job));
		}
		else	// if(choice==2)
		{
			System.out.print("학과 : "); major=sc.nextLine();
			addFriendInfo(new UnivFriend(name, phoneNum, addr, major));
		}
		System.out.println("입력 완료! \n");
	}
	
	public void showAllData()
	{
		for(int i=0; i<numOfFriends; i++)
		{
			myFriends[i].showData();
			System.out.println("");
		}
	}
	
	public void showAllSimpleData()
	{
		for(int i=0; i<numOfFriends; i++)
		{
			myFriends[i].showBasicInfo();
			System.out.println("");
		}
	}
}

class MyFriendInfoBook
{
	public static void main(String[] args)
	{
		FriendInfoHandler handler=new FriendInfoHandler(10);
		
		while(true)
		{			
			System.out.println("*** 메뉴 선택 ***");
			System.out.println("1. 고교 정보 저장");
			System.out.println("2. 대학 친구 저장");
			System.out.println("3. 전체 정보 출력");
			System.out.println("4. 기본 정보 출력");			
			System.out.println("5. 프로그램 종료");
			System.out.print("선택>> ");
			
			Scanner sc=new Scanner(System.in);
			int choice=sc.nextInt();

			switch(choice)
			{
			case 1: case 2:
				handler.addFriend(choice);
				break;
			case 3:
				handler.showAllData();
				break;
			case 4:
				handler.showAllSimpleData();
				break;
			case 5:
				System.out.println("프로그램을 종료합니다.");
				return;
			}
		}
	}
}

 

A. 내가 생각한 답

import java.util.Scanner;
class FriendMain
{
	public static void main(String[] args)
	{
		Scanner sc = new Scanner(System.in);

		String name, phoneNumber,adress,company,major = null;
		int friend =0;
		int size=100;
		Friend [] arr = new Friend[100];
		int cnt=0;
		
		while(true)
		{
			System.out.println("*** 메뉴 선택 ***");
			System.out.println("1. 고교 정보 저장");
			System.out.println("2. 대학 친구 저장");
			System.out.println("3. 전체 정보 출력");
			System.out.println("4. 전체 기본 정보 출력");
			System.out.println("5. 프로그램 종료");
			System.out.println("선택>>");
			friend = sc.nextInt();
			sc.nextLine();
		
			switch(friend)
			{
			case 1 : 
				System.out.println("고교 친구 정보 저장을 시작합니다");
				System.out.print("이름 : ");
				name = sc.nextLine();	
				System.out.print("전화번호 : ");
				phoneNumber = sc.nextLine();
				System.out.print("주소 : ");					
				adress = sc.nextLine();
				System.out.print("직장 : ");
				company = sc.nextLine();
				arr[cnt++] = new HighFriend(name, phoneNumber, adress, company);
				break;
					
			case 2 :
				System.out.println("대학 친구 정보 저장을 시작합니다");
				System.out.print("이름 : ");
				name = sc.nextLine();	
				System.out.print("전화번호 : ");
				phoneNumber = sc.nextLine();
				System.out.print("주소 : ");
				adress = sc.nextLine();
				System.out.print("전공 : ");
				major = sc.nextLine();
				arr[cnt++] = new UnivFriend(name, phoneNumber,adress, major);
				break;

			case 3 :
				System.out.println("전체 정보를 출력합니다.");
				for(int i=0;i<cnt;i++)
					arr[i].showData();
				break;
						
			case 4 : 
				System.out.println("전체 기본 정보를 출력합니다.");
				for(int i=0;i<cnt;i++)
					arr[i].showBasicInfo();
				break;
					
			case 5 :
				System.out.println("프로그램을 종료합니다.");
				return;
			default :
				System.out.println("잘못 입력하셨습니다. 다시 선택해주세요");
				
			}
		}
	}
}		
class Friend
{
	private String name;
	private String phoneNumber;
	private String adress;

	public Friend(String name, String phoneNumber, String adress)
	{
		this.name = name;
		this.phoneNumber=phoneNumber;
		this.adress=adress;
	}
	public void showData()
	{
		System.out.println("이름 : "+getName());
		System.out.println("전화번호 : "+getPhoneNumber());
		System.out.println("주소 : "+adress);
	}
		
	public void showBasicInfo()
	{
		System.out.println("이름 : "+name);
		System.out.println("전화번호 : "+phoneNumber);
	}
	public String getName()
	{
		return name;
	}
	public String getPhoneNumber()
	{
		return phoneNumber;
	}
	public String getAdress()
	{
		return adress;
	}
	
}

class HighFriend extends Friend
{
	private String company;
	
	public HighFriend(String name, String phoneNumber, String adress, String company)
	{
		super(name, phoneNumber, adress);
		this.company = company;
	}

	public void showData()
	{
		System.out.println("이름 : "+getName());
		System.out.println("전화번호 : "+getPhoneNumber());
		System.out.println("주소 : "+getAdress());
		System.out.println("직장 : "+company);
	}	

	public void showBasicInfo()
	{
		System.out.println("이름 : "+getName());
		System.out.println("전화번호 : "+getPhoneNumber());
		System.out.println("직장 : "+company);
	}
}

class UnivFriend extends Friend
{
	private String major;
	
	public UnivFriend(String name, String phoneNumber, String adress, String major)
	{
		super(name, phoneNumber, adress);
		this.major = major;
	}

	public void showData()
	{
		System.out.println("이름 : "+getName());
		System.out.println("전화번호 : "+getPhoneNumber());
		System.out.println("주소 : "+getAdress());
		System.out.println("전공 : "+major);
	}

	public void showBasicInfo()
	{
		System.out.println("이름 : "+getName());
		System.out.println("전공 : "+major);
	}
}

 

# 상속의 정의

  상속하는 클래스와 상속받는 클래스 간의 일관된 규칙성을 주기 위해 상속을 사용한다.

  상속을 통해 연관된 일련의 클래스에 대한 공통적인 규약을 정의할 수 있다.

 

#abstract : 상속 등의 목적으로 만든 객체 생성 원하지 않는 클래스에

            abstract을 붙여주면 추상클래스, 추상메소드가 되어 객체 생성할 수 없게 된다.

 

- 추상메소드

ex)

public abstract void AAA

 

- abstract를 메소드에 붙이면 추상메소드이며,

  클래스에 단 한 개만이라도 추상메소드가 존재한다면 그 클래스는 반드시 abstract으로 선언해주어야 한다.

 

 abstract 메소드가 없어도 abstract클래스로 만들 수 있다.

 하지만 abstract 메소드가 있다면 반드시 abstract 클래스로 만들어야 한다.

 

abstract메소드가 있는 클래스를 상속하는 클래스는 (강제조건)

① abstract 메소드로 만들거나

ex)

abstract class AAA
{
	public abstract void printHi()
} 

class BBB extends AAA
{
	public abstract void printHi()
}

  

몸체가 있는 형태로 메소드 오버라이딩 해줘야 한다

ex)

abstract class AAA
{
	public abstract void printHi()
} 

class BBB extends AAA
{
	public abstract void printHi()
	{
		System.out.println("Hi");
	}	
}

# 참고자료 내용

상속을 통해 연관된 일련의 클래스에 대한 공통적인 규약을 정의할 수 있다.

- 이전에 개발해 놓은 클래스의 재활용을 보인 사례는 매우 드물다.

   즉, 상속은 재활용의 측면에서 바라보면 별로 매력적이지 않다!

   그리고 재활용에 대한 이슈는 객체지향 패러다임에서

   CBD(Component Based Development)라는 패러다임으로 옮겨갔다.

 

- 객체지향이 재활용의 관점에서 실패한 이유

  객체지향에서 언급하는 재활용은 클래스 단위의 재활용이다.

  그런데 이는 다음과 같은 문제점을 안고 있다.

@ 클래스 하나를 재활용하는 것이 새롭게 디자인하는 것보다 더 큰 노력이 든다.

@ 재활용을 고려해서 클래스를 디자인할 경우, 설계에 필요한 시간이 몇 배 더 길어진다.

 

- 인스턴스 자동 초기화 값

자료형 디폴트 값
int 0
long 0
double 0
boolean false
String(or any object) null

 

- 접근제어지시자 中

  private 멤버변수도 상속이 되지만 간접적으로 접근해야 한다.

  protected는 다른 패키지에 존재할지라도 상속관계에 놓이면 접근을 허용한다.

 

- UI(User Interface) : 프로그램 사용자의 입력을 받아들이고, 프로그램의 출력을 표현하기 위한 화면을 의미한다.

                   자바는 이러한 화면의 디자인을 위한 클래스들을 AWT, SWING라는 패키지를 통해 제공하고 있다.

 

#모든 클래스가 상속하는 클래스는 Object (Why? 자바의 모든 인스턴스에 공통된 기준을 적용하기 위해)

  클래스를 정의할 때 다른 어떤 클래스도 상속하지 않으면(키워드 extends를 사용하지 않으면),

  해당 클래스는 java.lang 패키지에 묶여있는 Object 클래스를 상속하게 된다.

 

  즉, 아래의 클래스 2개는 동일한 의미다. 

class MyClass
{
}

class MyClass extends Object 
{
}

이렇듯 모든 클래스는 직접적으로 혹은 간접적으로 Object 클래스를 상속하게 되어 있다.

따라서 다음과 같은 코드의 구성이 가능하다.

Object obj1 = new MyClass();
Object obj2 = new int[5];	// 배열도 인스턴스이므로 참조 가능하다

 

- Object 클래스에는 다음의 메소드가 정의되어 있다. 

 public String toString() 
 {
 }

오브젝트 클래스가 가지고 있는 이 메소드를 클래스에 넣는 것은 오버라이딩 하는 개념이라 할 수 있다.

 

- System.out.println오버로딩 되어있는 메소드인데,

  그 중 하나가 다음과 같이 정의되어 있기 때문에 어떠한 클래스의 인스턴스이건 인자로 전달될 수 있는 것이다.

 

public void println(Object x)

@ 모든 인스턴스는(인스턴스의 참조 값은) System.out.println의 인자로 전달될 수 있다.

@ 인자로 전달되면, 해당 인스턴스의 toString 메소드가 호출되면서 반환되는 문자열이 출력된다.

 

- toString 메소드는 기본적으로 오버라이딩 해 두면 좋다. 

  자바의 API 문서에서는 toString 메소드에 대해서 다음과 같이 언급하고 있다.

 

@ toString 메소드는 인스턴스의 정보를 문자열의 형태로 반환하기 위한 메소드이다.

@ 가급적이면 toString 메소드를 오버라이딩을 해서 인스턴스에 대한 정보를 적절히 표현할 수 있도록 하는 것이 좋다.

 

 

728x90