# 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 메소드를 오버라이딩을 해서 인스턴스에 대한 정보를 적절히 표현할 수 있도록 하는 것이 좋다.
'SW > Java' 카테고리의 다른 글
[필기정리]Day15 - Lotto생성기 및 숫자야구게임 문제 (0) | 2020.06.30 |
---|---|
[필기정리]Day14 - 전화번호 관리 프로그램 문제 04단계 (0) | 2020.06.29 |
[필기정리]Day12 - 상속 (0) | 2020.06.25 |
[필기정리]Day11 - 전화번호 관리 프로그램 문제 03단계 (0) | 2020.06.24 |
[필기정리]Day10 - 2차원배열, 배열 예제문제 등 (0) | 2020.06.24 |