상속에 대해서 알아보자.
extends(상속)
상속(inherit)상속은 부모가 보유하고 있는 재산(필드: 멤버 메써드와 멤버 변수) 중 일부/전부 자식이 물려받는것.
상속을 클래스에서 발생하는데 A클래스를 상속받는 B클래스는 B extends A식으로 표현한다.
클래스 상속은 객체의 재사용이라는 장점뿐 아니라, 코드의 간결성을 제공해주는 객체 지향언어의 최고 장점이라 할 수 있다. 그러므로 잘 정의된 부모 클래스가 있다면 자식 클래스의 작성이 간편해진다는 장점이 있다.
결국 상속은 부모 A클래스에 있는 멤버들을 자식 B클래스, 자식 C클래스에서 사용할 수 잇게 해서 객체의 재사용과 코드의 간결함을 이룰 수 있다.
잘 정의 된 부모 클래스(슈퍼클래스)의 필드들을 자식 클래스(서브클래스)에서 불러다 사용한다. 하지만 부모 클래스에서 private로 선언된 멤버는 자식클래스에서 사용할 수 없다.
class_B extends class_A 식으로 해주는데 class_A가 부모, class_B가 자식 클래스이다.
오버라이딩이란 상속된 부모의 메써드를 자식 클래스에서 재정의 해서 사용하는 것을 말한다.
=>자바에서는 Method Over- loading 또는 Class Over-riding을 사용한다.
OOP(Object Oriented Programing :객체 지향 언어=> Java, C++, ....)는 클래스 개념을 사용해서 객체를 만들고 이 객체로 모든 현상을 설명한는 프로그래밍 기법
Object가 최상위 객체이다.
package java08;
import java.security.KeyStore.PrivateKeyEntry;
class Parent{
//다음처럼 2개의 멤버 변수 정의
private int money = 200;
private String str="서울";
//다음처럼 4개의 멤버 메써드 정의
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money; //클래스 내에서 자신의 변수를 지시할 때 this.변수_명 사용
}
public String getStr() {
return str;
}
public void setStr() {
this.str = str; //parent의 str
}
}// 여기까지 부모클래스 정의
class Child extends Parent{
private String car = "Grandeur"; //자식 클래스에서 하나의 변수 정의
// 자식 클래스에서 두 개의 메써드 정의
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
}
public class Test01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Child cl = new Child(); //Child 클래스에서 c1 객체 생성<= 인스턴스화 한다고 함
System.out.println(cl.getCar()); // Child가 자신의 멤버 메써드 사용
System.out.println(cl.getMoney()); //Child는 Parent에서 상속받은 Parent 멤버 메써드 사용
if(cl instanceof Parent) // instanceof는 객체화 여부를 점검하는데 boolean으로 결과 보임
System.out.println("cl은 Parrent의 자식이다.");
System.out.println("------------");
Child ch = new Child(); //Child 클래스에서 새로운 객체 생성
Parent pr = new Parent(); //Parent 클래스에서 새로운 객체 생성
pr = (Parent)ch;
ch = (Child)pr;
// 부모를 자식에게 캐스팅(형변환)함, 부모를 자식에 대입함으로써 자식은 자신의 모든 필드와
// 부모의 모든 필드를 사용할 수 있음. 클래스 캐스팅은 많이 사용하지 않는다!!
System.out.println(ch.getCar()); //자식이 자식 멤버사용
System.out.println(ch.getMoney()); //자식이 부모 멤버 사용
System.out.println(ch.getStr()); //자식이 부모 멤버 사용
System.out.println("-------------");
pr =ch;
//자식을 부모에게 대입함, 부모는 자신의 멤버들만 사용할 수 있음!!!
System.out.println(pr.getMoney()); //부모는 자신의 멤버만 사용가능
System.out.println(pr.getStr());
// System.out.println(pr.getCar()); // 부모가 자식 멤버 사용 불가!!
// System.out.println((Child)pr.getCar());//오류!!
}
}

** 메써드 오버로딩은 하나의 메써드_명에 인자, 반환값만 다르게 해서 여러개를 만들어 두고 호출 할 때 인자와 반환값에 맞는 메써드를 선택해서 사용하게 하는 기법이고,
**메써드는 오버라이딩은 부모 클래스의 멤버 메써드를 (상속받은) 자식클래스에서 부모 멤버의 동일한 메써드_명으로 내용만 다르게 해서 지정하는 기법이다. 접근 범위는 보통 부모보다 넓게 잡아준다.
**Annotation은 '@Override' 식으로 표기한뒤 그 아래에 내용을 써주는데 '@내용'은 일종의 주석과 같이 실제 실행되지는 않지만 그 아래의 내용을 프로세서에게 알려서 처리속도를 빠르게 해준다.
package java08;
class Animal{ //동물 이라는 큰 클래스를 부모로 정의해두고, 모든 자식 클래스들이 가질수
//있는 특성을 정의해 둠
int leg;
String shout;
public int getLeg() {
return -1; //overriding을 위한 설정이지만 하는 일은 없다.
}
public String getShout() {
return shout;
}
public void setShout(String shout) {
this.shout =shout;
}
}
class Duck extends Animal{
private String wing = "날개가 있어요";
public String getWing() {
return wing;
}
public int getLeg() {
System.out.println("Duck의 오버라이딩 메써드");
return 2; // 이 클래스에는 leg가 없지만 상속받았기 때문에 부모의 멤버 면수를 사용
}
}
class Ant extends Animal{
private String legs = "다리가 많아요";
public String getLegs() {
return legs; //부모의 멤버 변수를 사용하지 않고 자신의 변수를 사용하므로 legs
}
public int getLeg() { // 부모의 getLeg() 메써드를 가져와서 다음처럼 print하는
//메써드 오버라이딩
System.out.println("Ant의 오버라이딩 메써드");
return 8; //부모 변수를 사용하므로 leg로 반환
}
}
public class Test02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Duck duck = new Duck();
System.out.println("날개 : "+duck.getWing()); //자식 메써드 이용
System.out.println("다리 : "+duck.getLeg()); //부모 메써드 이용
duck.setShout("꽥꽥");
System.out.println("울음소리 : "+duck.getShout()); //부모 메써드 이용
Ant ant = new Ant();
// System.out.println("날개 : "+ant.getWing());
System.out.println("다리 : "+ant.getLeg()); //자식 메써드 이용
duck.setShout("스물스물");
System.out.println("울음소리 : "+ant.getShout()); //부모 메써드 이용
}
}

package java08;
class Book{
String title;
String genre;
void printBook() {
System.out.println("제목:"+ title);
System.out.println("장르 :"+genre);
}
}
class Novel extends Book{
String writer;
void printNov() {
printBook();
System.out.println("저자 : "+writer);
}
}
class Magazine extends Book{
int day;
void printMag() {
printBook();
System.out.println("발행일 : "+day+"일");
}
}
public class Test04 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Novel nov = new Novel();
nov.title="구운몽";
nov.genre="고전문학";
nov.writer="김만중";
Magazine mag = new Magazine();
mag.title="월간 자바";
mag.genre="프로그래밍";
mag.day=20;
nov.printNov(); // 함수 호출
System.out.println("--------------------");
mag.printMag(); // 함수 호출
}
}

**Private가 붙은 멤버_변수/멤버_메써드는 다른 오브젝트에서 사용될 수 없고, 서브 클래스로 상속될 수도 없다.
package java08;
import java.awt.print.Printable;
class Person{
// private String name; //외부에서 그냥 불러다 쓰지 못하고 이 필드에 잇는 메써드로 접근 가능
String name; //외부에서 그냥 불러다 써도 됨
void setName(String n) {
this.name=n;
}
String getName(){
return name;
}
}
class Girl extends Person{
void print() {
System.out.println(getName()+"양 ");
}
}
public class Test05 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Girl names =new Girl();
names.setName("메리"); //위에서 private로 했으면 부모 메써드를 호출해서 접근한다.
// nara.name="메리"; // 위에서 private로 하지 않으면 바로 접근도 가능
names.print(); //여기서 System.out.println()을 필요 없이 Girl 클래스에 있는
//print()메써드를 호출하면 출력해줄 것이다.
}
}

**생성자
생성자는 클래스 _명과 동일한 이름으로 메써드 생성 ( 생성자 (Construct:C 프로그램에서 구조체))
라고 부르는데
클래스_명 객체_명 = new 클래스_명(): 구문에서 뒤의 클래스_명이 바로 생성자를 호출
한다는 의미이다.
인스턴스화 할때 제일 먼저 호출되어 실행되는 일종의 메써드이다.
생성자는 인스턴스 필드 값을 초기화시킨다.
public 클래스_명(매개_변수){...}구문이다. 생성자_명은 클래스_명과
동일해야한다.
원래는 public class Constructor {...}식으로 main()함수위에 기술해야 하지만
자동으로 입력되기 때문에 일부러 쓸 필요는 없다.
package java08;
class Parents {
public Parents(int n) { //생성자 메써드
System.out.println("부모 클래스"+n);
}
}
class Childs extends Parents{
public Childs() { // 생성자 메써드
super(1); // 객체 생성 없이 부모 클래스 Prent 호출
System.out.println("자식 클래스");
}
}
public class Test06 {
public static void main(String[] args) {
// TODO Auto-generated method stub
// Childs ch = new Childs();
new Childs();
//자식 클래스에서 객체를 생성하면 자식의 생성자가 호출되지만 super()로 부모의 생성자를
//먼저 호출했기 때문에 부모 클래스의 생성자에 접근하게 된다.
// System.out.println("부모 클래스");
}//main
}

package java08;
class Animalss{
String name;
int age;
void printPet() {
System.out.println("이름 : "+name);
System.out.println("나이 : "+age);
}
}
class Cat extends Animalss{
String variety;
void printPet() { //method overriding
super.printPet(); //객체 생성 없이 부모의 메써드 호출
System.out.println("종류:"+variety); // 자신의 변수로 무보의 메써드를 호출해서 작업
}
}
public class Test07 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Cat cat = new Cat();
cat.name= "양순이";
cat.age = 5;
cat.variety = "페르시안";
cat.printPet(); // 자식 메써드 호출이지만 부모 메써드도 이용
}
}

** 클래스에서의 접근 제한자
제한자는 외부에서 해당 접근할 수 있는 범위를 표시하는데
final: 부모 필드나 클래스에 붙이면 상속을 못해주고 필드 값도 변경하지 못한다.
private: 부모 클래스에 붙이면 상속이 불가하고 다른 객체들이 이 클래스를 사용할 수 없다. 클래스를 보호해서 캡슐화(encapsulation:은닉) 할 때 사용된다.
protected: 부모 클래스에 붙이면 상속받은 클래스에서만 사용할 수 있다.
public:클래스에 붙이면 누구나 접속해서 이 클래스의 객체를 사용할 수 있다.
default:클래스에 특별히 이런 접근 제한자를 붙이지 않으면 해당 클래스의 필드는 해당 패키지 안에서만 사용된다.
this는 로컬 변수나 매개 변수에서 클래스의 변수 name과 같은 변수가 있을때 this.name식으로 해주면 해당 클래스의 변수를 지시한다. 간단히 말해서 this는 클래스에 있는 멤버변수 등을 지시한다.
추상클래스와 추상 메써드:
이들은 클래스에서 수행할 명령어들을 지정하지 않고 호출하는 방법만 기술한 메써드를 추상 메써드라고 하고, 추상 메써드를 가지고 있는 클래스를 추상 클래스라고 한다.
abstract를 앞에 붙임. 프로그래밍 강제할 때 사용하며 기본적으로 지켜야 할 틀을 제공해서 각 서브 클래스에서 이 클래스를 불러서 구현시킬 때 사용된다.
'JAVA' 카테고리의 다른 글
| [JAVA]인터페이스, 열거형, 내부클래스 (0) | 2022.07.29 |
|---|---|
| [JAVA]Object, 제네릭 클래스, 추상 메써드 (0) | 2022.07.28 |
| [JAVA] Overload/ Overriding (0) | 2022.07.26 |
| [JAVA] 가변 인수 (0) | 2022.07.26 |
| [JAVA]클래스/ 메써드 (0) | 2022.07.26 |
댓글