contents
chapter07
1.상속이란?
2.오버라이딩(overring)
3.상속과 생성자
1).super()
2)Object 클래스
4.pakage와 import
1)package란?
2)pakage 만들기
3)import
5.제어자
1)접근 제어자
2)static
3)final
6.다형성(polymorphism)
1)다형성이란?
2)참조변수와 인스턴스 간의 관계
3)다형성의 활용
chapter08
1.추상 메서드와 추상 클래스
1)추상 메서드
2)추상 클래스
2.인터페이스(Interface)
1)인터페이스란?
2)인터페이스의 문법
3)인터페이스의 실제 활용
4)인터페이스와 다형성
자바개념정리
--------------------------------------------------------------------
chapter07
1.상속이란?
-새로운 클래스를 작성할 떄 기존에 존재하는 클래스를 물려받아 이용함. 기존의 클래스가 가진 멤버를 물려받기 때문에 새롭게 작성해야 할 코드의 양이 줄어드는 효과가 있음. 이때 자신의 멤버를 물려주는 클래스를 부모 클래스 또는 조상 클래스라고 하고 상속받는 클래스를 자식 클래스 또는 자손 클래스라고 함
-상속할 때는 새롭게 작성할 클새스 선언 부분 뒤어 'extends 부모 클래스 이름'을 붙임
class Perents{ } class Child extends Parent{ } //Parents 클래스의 멤버들을 상속받음 |
-상속을 사용하는 이유는 코드를 재사용하고 코드의 중복을 줄이기 위해서임. 다만 상속을 할 떄 생성자는 상속되지 않음
<'사람'클래스를 선언한 다음 '학생' 클래스에서 상속받는 프로그램>
package ch07;
class Person{ //사람 클래스 void breath() { System.out.println("숨쉬기"); } void eat() { System.out.println("밥먹기"); } void say() { System.out.println("말하기"); } } class Student extends Person{// 사람 클래스를 상속한 학생 클래스 Student(){ super(); } void learn() { System.out.println("배우기"); } @Override void breath() { System.out.println("깊은숨"); } } class Teacher extends Person{ // 사람 클래스를 상속한 상속 클래스 Teacher(){ super(); //부모객체를 만드는 생성자 } void teach() { System.out.println("가르치기"); } } public class exam40 { public static void main(String[] args) { Student s1 = new Student(); //학생 인스턴스 s1 생성 s1.breath(); //사람 클래스의 breath 메서드를 상속받았음 s1.learn(); Teacher t1 = new Teacher(); //선생 인스턴스 t1 생성 t1.eat(); //사람 클래스의 eat 메서드를 상속받았음. t1.teach(); } } |
-자바에서는 단일 상속만을 허용함
class Test extends B, extends C{ } //에러발생, 다중상속 불가 |
-다른 객체지향언어에서는 여러 클래스로부터 상속을 받을 수 있지만 자바에서는 다중속성을 허용하지 않음
final class Parent{ } class Child extends Parent{ } //에러발생 |
-자바에서 상속이 가능하지 않은 경우가 있는데 클래스 앞에 final이 붙은 경우레 상속이 불가능함
-만약 현재 클래스가 어떤 계층구조(hierarchy)를 가지고 있는지 궁금하다면 해당 클래스에 커서를 옮긴 후, ctrl + T를 누르면 확인이 가능
2.오버라이딩(overring)
-오버라이딩은 자손 클래스에서 부모 클래스로부터 물려받은 메서드를 다시 작성하는 것을 말함
-다시 작성하는 이유는 부모로부터 메서드를 상속받았지만 자손 클래스에서는 부모와는 다르게 동작해야할 때도 있기 때문임. 오버라이딩을 할 때는 부모 클래스의 메서드와 선언부가 일치하는 메서드를 작성해야 함
class Parents{ void method1(){ //부모 클래스의 메서드 } } class Child extends Parents{ void method1(){ //자손 클래스에서 메서드 내용을 재정의 } } |
-자손 인스턴스에서 오버라이딩을 한 메서드를 호출 할 경우 이름이 같은 메서드가 부모 클래스에 있더라도 자손 클래스에서 다시 작성한 메서드가 호출됨
-즉 부모로부터 물려받은 클래스가 마음에 들지 않을 때, 자식 클래스는 언제든지 부모 클래스의 메서드를 재정의해서 사용함
-만약 재정의할 메서드를 자동으로 선택해서 추가하려면 이클립스 메뉴의 [source] - [Override/Implement Methods] 항목을 클릭함
-자동으로 재정의할 메서드가 추가되며 @Override로 추가된 부분은 annotation 주석기능으로서 생략이 가능하며, 가독성을 높여주기 위해 생성된 것임
-이미 오버라이딩을 한 상태이지만 부모의 메서드 동작이 필요할 경우 자손 클래스에서 부모의 메서드를 참조할 수 있음. 자신의 인스턴스를 가리키는 참조변수 this가 있듯이 자신의 상위 클래스를 가리키는 참조변수 super가 존재함
TIPS
-this: 인스턴스들이 메서드를 호출할 때, 메서드는 공용으로 사용하게 됨. 이때 각 인스턴스의 정보를 저장하는 변수를 this라고 함
-this(): 클래스에서 생성자의 임무가 겹칠 때, 한 생성자로 임무를 집중시킬 수 있음
생성자(){
this(10); 인수 한 개짜리 생성자 a 변수에 10을 전달함
}
생성자(int a){
}
-super: 상속을 하면 자식의 멤버(변수, 메서드)와 이름이 겹치게 될 때가 있는데 이를 구분하기 위해 super.변수, super.메서드()를 사용하면 자식의 멤버가 호출되지 않고 상속받은 부모의 멤버를 호출할 수 있게 됨
-super(): 자식 생성자에서 부모 생성자를 호출할 때 사용함, super(값, 값,...)하게 되면 인자 있는 부모 생성자를 명시적으로 호출함
3.상속과 생성자
-자손 클래스의 생성자 작업을 할 때 부모 클래스의 생성자도 반드시 호출해주어야함
1).super()
-부모 클래스의 생성자 호출은 상위 클래스를 의미하는 super라는 키워드에 ()를 붙인 super()을 통해 이루어짐. 부모 클래스 호출은 무조건 자식 클래스 생성자 첫 줄에서 이루어짐. 만약 자식의 생성자 내부에 부모 클래스의 생성자를 따로 작성하지 않았다면 자동적으로 컴파일러는 자식 클래스의 생성자 첫 줄에 super();을 추가함
package ch07;
class Car2{ int wheel; int speed; String color; Car2(){} Car2(String color){ this.color = color; } } class SportsCar extends Car2{ int speedLimit; //제한속도 km SportsCar(String color, int speedLimit){ // super(color); this.color = color; this.speedLimit = speedLimit; } } public class exam43 { public static void main(String[] args) { SportsCar sportsCar1 = new SportsCar("red", 330); System.out.println(sportsCar1.color); System.out.println(sportsCar1.speedLimit); } } |
2)Object 클래스
-object 클래스는 모든 클래스의 조상인 클래스임. 어떤 클래스라도 상속 관계를 따라 거슬러 올라가면 마지막에는 Object 클래스가 있음. Object 클래스는 가장 조상인 클래스이기 떄문에 누구의 상속도 받지 않음
-만약 아무런 상속을 받지 않는 독자적인 클래스를 만들었다면 컴파일러는 자동으로 Object 클래스를 상속하는 문구를 추가함
class Tree extends Object{ //내부 멤버 } |
-따라서 모든 클래스는 Object 클래스를 자동으로 상속하기 때문에 Object 클래스 내부에 정의된 멤버들을 사용함. ex)toString(), equals()
-상속관계에 있는 클래스에서 반드시 상위 클래스의 생성자를 호출해야 하는 규칙도 결국에는 Object 클래스까지 거슬러 올라감
4.package와 import
-패키지를 사용하면 클래스들을 쉽게 다룰 수 있음
1)package란?
-패키지란 클래스를 모아놓은 일종의 집합임. 만약 단순한 프로그램이 아니라 규모가 큰 작업을 할 때는 상당히 많은 클래스를 사용할 것임. 이때 유지보수 및 관리를 용이하게 하기 위해서 관련 있는 클래스끼리 묶어서 분리하는 일종의 디렉터리로서 package를 사용함
2)package 만들기
(1)src 폴더에 마우스를 우클릭하고 [New] - [Package]를 클릭
(2)[New Java Package] 대화상자가 나타나면 [name]에 패키지 이름을 적어줌. 클래스와 구분하기 위해 보통은 패키지 이름은 소문자로 작성함. 작성을 완료하였으면 [Finish] 버튼을 클릭
(3)왼쪽에 패키지가 만들어 진것을 확인함. 패키지에서 마우스 우클릭을 눌러 [New] - [Class]를 선택
(4)클래스의 이름을 입력한 다음 [Finish]] 버튼을 클릭
(5)생성된 클래스의 소스코드를 보면 맨 첫 줄에 package 이름;라고 작성되어 있는 것을 확인함. 이는 현재의 클래스가 이름 package에 속해있는 클래스라는 것을 의미함. 만약 패키지를 만들지 않고 클래스를 생성하면 자동으로 defalt package에 속하게 됨
3)import
-다른 패키지에 있는 클래스를 사용하고 싶을 때는 클래스의 이름으로 참조함
-참조해야할 클래스가 많아지고 다영해진다면 일일이 경로를 써주어야 하기 때문에 코드가 상당히 복잡해짐. 이때 경로를 써주는 것을 생략하는 방법이 있는데 이것이 바로 import임
import 패키지명.클래스명; |
-모든 클래스를 사용하고 싶다면 일일이 import문을 작성할 필요 없이 클래스명 자리에 *를 붙여주면 됨
import java.util.*; //util 패키지의 모든 클래스 사용 |
5.제어자
-제어자란 클래스난 멤버의 사용을 제어하기 위해서 사용됨. 제어자의 종류에는 외부에서 접근하는 것을 막는 접근제어자와 클래스 멤버를 의미하는 static, 상수를 만들거나 상속을 종결시키는 final 등이 있음
1)접근 제어자
-접근 제어자는 외부에서 접근할 수 있는 정도와 범위를 정해줌. 접근 제어자로는 허용 범위가 넓은 순서대로 public, protected, default, private가 있음. 여기서 default는 아무런 접근 제어자를 작성하지 않았을 경우를 말함
-public: 접근 제한이 없음 -> 클래스의 자식(변수, 함수) -protected: 같은 패키지 내에서와 자손 클래스에서 접근 가능 -default: 같은 패키지 내에서만 접근 가능(생략) -private: 같은 클래스 내에서만 접근 가능 |
cf)not visible 에러: 접근제어자 안만듬
*규칙: 접근제어자 상태 리턴타입 변수명
instance void a( ){ } 함수 => 이름앞에 3개 사용
static int a; 변수
<public 선언>
package ch07;
class User{ public String name; public int age; User(String name, int age){ //매개변수를 가진 생성자 this.name = name; this.age = age; } } public class exam46_1 { public static void main(String[] args) { User user1 = new User("철수", 20); //인스턴스 생성 User user2 = new User("영희", 19); //인스턴스 생성 System.out.println(user2.name + "의 나이는" + user2.age); user2.age = 99; System.out.println(user2.name + "의 나이는" + user2.age); } } |
실행 결과
영희의 나이는19
영희의 나이는99 |
<private>
package ch07;
class User2 { private String name; private int age; User2(String name, int age) { // 매개변수를 가진 생성자 this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } } public class exam46_2 { public static void main(String[] args) { User2 user1 = new User2("철수", 20); // 인스턴스 생성 User2 user2 = new User2("영희", 19); // 인스턴스 생성 // user2.age = 99; //에러빌생. 직접적 접근 불가 user2.setAge(20); System.out.println(user2.getName() + "의 나이는" + user2.getAge()); } } |
실행 결과
영희의 나이는20
|
-클래스 내부에 getName, setName 메서드를 구현해서 간접적으로 값에 접근할 수 있도록 함. 이러한 방식으로 구현하면 데이터의 안정성이 확보됨. 이름을 반환하는 get형식의 메서드를 게터(getter)라고 하고 변수의 값을 설정하는 set형식의 메서드를 셋터(setter)라고 함. 만약 셋터를 설정하지 않았다면 데이터의 조회만 가능한 클래스가 됨
2)static
-static 제어자는 변수나 메서드 앞에 붙어서 이 멤버가 클래스 멤버라는 것을 의미함. 클래스 멤버는 처음 클래스가 메모리에 로드될 때 생성되기 때문에 인스턴스를 생성하지 않아도 사용 가능함
3)final
-final은 문자 그대로 '종결의'라는 의미를 가짐. final이 붙으면 내용이나 값을 변경하지 못하게 됨
-프로그램이 샐행되는 중에 변경 될 수 없게 하거나 오버라이딩과 상속을 의도적으로 막기 위해서 final을 사용함
final 변수: 값을 더 이상 변경할 수 없는 상수 final 메서드: 내용을 더 이상 변경할 수 없는 메서드, 오버라이딩 불가 final 클래스: 내용을 더 이상 변경할 수 없는 클래스, 상속불가 |
6.다형성(polymorphism)
-다형성은 객체지향언어에서 객체의 자료형을 변경하는 것을 말함
1)다형성이란?
사전적 의미로는 '여러 형태를 가지는 성질'을 뜻함. 객체지향 개념에서 다형성은 '한 가지 타입이 여러 가지 형태의 인스턴스를 가질 수 있다'라는 의미임. 특히, 부모 타입 변수에는 모든 자식 인스턴스들이 대입될 수 있는데, 이 점은 객체지향언어의 중요한 특징 중의 하나임
-지금까지는 인스턴스를 생성하고 참조변수에 할당할 때 인스턴스와 참조변수의 클래스 타입을 동일하게 작성함.
A obj = new A(); |
-그러나 다형성의 정의에 따라 조상 클래스 타입의 참조변수로 자손 클래스 타입의 객체를 참조할 수도 있음
A obj = new B(); (클래스 B가 A를 상속할 때) |
-참조변수 obj 하나로 A타입의 인스턴스를 참조할 수 도, B타입의 인스턴스를 참조할 수도 있는데, 이것이 바로 다형성임
2)참조변수와 인스턴스 간의 관계
-다형성을 이용할 때 중요한 것 중의 하나는 조상 클래스 타입의 참조변수로 자손 인스턴스를 참조하는 것은 가능하지만 그 반대의 경우에는 에러가 발생한다는 것임.
-자손 클래스는 부모 클래스를 상속하면서 부모의 멤버들에 자신의 멤버들을 더해 확장됨
-부모 클래스의 참조변수에서 자손 클래스의 인스턴스를 참조할 때 주의할 점은 부모 클래스의 참조변수로 참조가 불가능한 멤버가 존재한다는 점임
3)다형성의 활용
package ch07;
class Animal{ //동물 클래스 void breath() { System.out.println("숨쉬기"); } } class Lion extends Animal{ //동물 클래스를 상속한 사자 클래스 public String toString() { return "사자"; } } class Rabbit extends Animal{ //동물 클레스를 상속한 토끼 클래스 public String toString() { return "토끼"; } } class Monkey extends Animal{ //동물 클레스를 상속한 원숭이 클래스 public String toString() { return "원숭이"; } } class Zookeeper{//사육사 클래스 void feed(Animal animal) { //사자에게 먹이주는 클래스 System.out.println(animal + "에게 먹이 주기"); } } public class exam51 { public static void main(String[] args) { Animal lion1 = new Lion(); //Lion 인스턴스 생성 Zookeeper james = new Zookeeper(); //james 이름의 사육사 인스턴스 생성 james.feed(lion1); //james가 lion1에게 먹이를 줌 Animal rabbit1 = new Rabbit(); //Lion 인스턴스 생성 james.feed(rabbit1); //james가 rabbit1에게 먹이를 줌 Animal monkey1 = new Monkey(); //Lion 인스턴스 생성 james.feed(monkey1); //james가 monkey1에게 먹이를 줌 } } |
실행 결과
사자에게 먹이 주기
토끼에게 먹이 주기 원숭이에게 먹이 주기 |
* feed(Animal animal) 중간에 거쳐가는 함수를 하나로 받음
chapter08
1.추상 메서드와 추상 클래스
-추상 클래스와 추상 메서드를 사용하면 자식 클래스에게 문법적인 제한을 줄 수 있음
1)추상 메서드
-추상 메서드는 선언부만 정의하고 구체적인 내용은 비워놓는 메서드임. 구체적인 내용을 적지 않았기 때문에 이를 상속받은 하위 클래스에서는 사용하려면 반드시 구현하라는 의미임
-추상 클래스를 선어하는 방법은 '추상적인'이라는 뜻의 제어자, abstract를 메서드면 앞에 붙여주면 됨. 그리고 구체적인 내용이 없으므로 괄호'{ }'를 생략하고 세미콜론 ';'을 붙여줌
abstract void methodA(); |
2)추상 클래스
-추상 클래스는 추상 메서드를 멤버로 가지는 클래스임. 추상 클래스는 일반적인 메서드도 가질 수 있지만 추상 메서드를 하나라도 포함하는 클래스임
-완전하지 않은 설계도로는 물건을 생산하지 못하듯이 추상 클래스로는 아직 인스턴스를 생성할 수 없음. 그러므로 추상 클래스는 그 자체로 사용되기보다는 자손 클래스를 완전하게 작성하기 위한 기본적인 틀로서 사용됨
-추상 클래스는 추상 메서드를 포함하기 때문에 이를 상속받은 자손 클래스는 반드시 추상 메서드를 구체적으로 작성해주어야 함
-추상 클래스를 선언하기 위해서는 클래스명 앞에 제어자 abstract를 붙여 선언함. 내부에 추상 메서드가 있다면 반드시 클래스명 앞에 abstract를 붙여야함
-추상 클래스를 상속받은 클래스들은 반드시 추상 메서드를 자신의 클래스에 맞게 구현하라는 강제성이 있음. 추상클래스를 사용함으로써 이를 상속하는 자손 클래스에게 문법적인 제한을 주는 것임. 또한 반대로 추상 클래스를 만들고 싶을 때는 자손 클래스들에서 사용되는 공통적인 부분을 묶어서 추상 메서드로 지정하여 작성함
<추상클래스>
package ch07;
abstract class Pokemon{ //포켓몬 추상 클래스 String name; abstract void attack(); // 공격 추상 메서드 abstract void sound(); // 소리 추상 메서드 public String getName() {// 포켓몬의 이름을 리턴 하는 메서드 return this.name; } } class Pikachu extends Pokemon{ // 피카츄 클래스 Pikachu(){// 이름을 지정하는 생성자 this.name = "피카츄"; } @Override void attack() {// 구체적으로 구현 System.out.println("전기공격"); } @Override void sound() {// 구체적으로 구현 System.out.println("피카 피카!"); } } class Squirtle extends Pokemon{ Squirtle(){ this.name = "꼬부기"; } @Override void attack() { System.out.println("물공격"); } @Override void sound() { System.out.println("꼬북 꼬북!"); } } public class exam54 { public static void main(String[] args) { Pikachu pikachu1 = new Pikachu(); System.out.println("이 포켓몬은:" + pikachu1.getName()); pikachu1.attack(); pikachu1.sound(); Squirtle squirtle1 = new Squirtle(); System.out.println("이 포켓몬은:" + squirtle1.getName()); squirtle1.attack(); squirtle1.sound(); } } |
실행 결과
이 포켓몬은:피카츄
전기공격 피카 피카! 이 포켓몬은:꼬부기 물공격 꼬북 꼬북! |
2.인터페이스(Interface)
-인터페이스는 객체간 상호 작용을 위한 일종의 규약임
1)인터페이스란?
-인터페이스(interface)란 inter(사이의) + face(마주하다)의 합성어임. 즉 물체들 사이에서 상호작용을 하기 위한 매개역할을 하는 것이 인터페이스임 ex)키보드, 마우스, 핸들, 버튼, 터치스크린
-클래스가 설계도라면 인터페이스는 설계할 때 필요한 목록을 써놓은 종이에 비유함. 종이를 바탕으로 설계도를 작성하듯 프로그래머는 인터페이스를 바탕으로 클래스를 작성함
2)인터페이스의 문법
-인터페이스는 상수와 추상 메서드를 멤버로 가질 수 있음. 추상 메서드와 일반 멤버를 모두 가질 수 있는 추상 클래스보다 더 기본적인 구조라고 함. 인터페이스는 키워드로 interface를 사용하며 제어자로 상수 앞에는 public final static을 메서드 앞에는 public abstract를 붙임
interface 인터페이스이름{ public static final 타입 이름 = 값; => 상수 piblic abstract 반환타입 메서드이름(매개변수); => 추상메서드 } |
-다만 제어자를 생략하더라도 에러가 발생하지는 않는데 이는 컴파일러에서 자동으로 이들 제어자를 추가하기 때문임
-인터페이스는 상속한다는 말 대신에 구현한다는 말을 사용함. 자손 클래스는 키워드 implements를 사용해서 인터페이스를 구현함. 인터페이스를 구현한 자손 클래스는 오버라이딩을 통하여 인터페이스 내부의 추상 메서드를 구체적으로 구현해야 함
interface A{ int a = 4; //제어자 생략가능 void methodA(); //제어자 생략가능 void methodB(); } class B implements A{ public void methodA(){ /*구체적인 구현, 오버라이딩*/ } public void methodB(){ /*구체적인 구현, 오버라이딩*/ } } |
-오버라이딩을 할 때는 부모의 접근제어자보다 더 넓거나 같은 범위의 제어자를 사용하므로, public 제어자를 붙이고 오버라이딩을 해야 함
-하나의 클래스가 상속을 받으면서 구현을 동시에 할 수도 있음
class B extends C implements A{ /* C의 멤버 A의 멤버 */ } |
-이때 자손 클래스는 부모 클래스의 멤버와 인터페이스의 멤버를 모두 갖게 됨
-또한 인터페이스 간에도 상속이 가능함. 클래스는 다중상속이 불가했지만 인테페이스는 다수의 인터페이스를 구현할 수 있으므로 다중상속이 가능함
interface A{ void methodA(); } interface B{ void methodB(); } interface C extends A, B{ } |
-C는추상 메서드 methodA와 methodB를 멤버로 상속받게 됨. 이때 C는 A와 B를 합친 종합적인 기능을 다루는 인터페이스임
3)인터페이스의 실제 활용
-인터페이스는 객체 간의 상호작용을 위한 일종의 규약임
-A프로그래머와 B프로그래머가 하나의 프로젝트를 진행했을 때, A프로그래머와 B프로그래머가 서로의 클래스가 완성되지 않았어도, 구현해야 할 기능들을 미리 협의하고 반환타입을 정해 놓으면 서로의 작업의 정도와는 무관하게 진행함. 바로 이런 약속과 같은 것이 인터페이스임
<여행 가이드 객체를 만들고 그 인스턴스는 레저, 관광, 음식 투어를 진행할 수 있게 만든 코드>
package ch07;
interface Providable { void leisureSport(); void sightseeing(); void food(); } class KoreaTour implements Providable { @Override public void leisureSport() { System.out.println("한강에서 수상스키 투어"); } @Override public void sightseeing() { System.out.println("경복궁 관람 투어"); } @Override public void food() { System.out.println("전주 비빔밥 투어"); } } class TourGuide { private Providable tour = new KoreaTour(); // 인터페이스로 타입선언 public void leisureSport() { tour.leisureSport(); } public void sighteeing() { tour.sightseeing(); } public void food() { tour.food(); } } public class exam55 { public static void main(String[] args) { TourGuide guide = new TourGuide(); guide.leisureSport(); guide.sighteeing(); guide.food(); } } |
실행 결과
한강에서 수상스키 투어
경복궁 관람 투어 전주 비빔밥 투어 |
-KoreaTour 클래스가 Providable 인터페이스를 구현하였으므로 인터페이스 내부의 추상 메서드를 모두 구체적으로 작성함. 그 다음 TourGuide 클래스는 인터페이스 타입인 참조변수를 선언함. 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조하는 것처럼 인터페이스도 이를 구현한 인스턴스의 참조가 가능함.
-이렇게 참조하게 되면 TourGuide 클래스는 KoreaTour 클래스와의 관계가 굉장히 느슨해짐. 왜냐하면 TourGuide 내부에 있는 메서드의 호출이 모두 Providable 인터페이스의 참조변수를 통해 가능하기 때문임
<만약 Guide가 일본에서 근무하게 되어 코드를 변경해야 할 경우>
class JapanTour implements Providable { @Override public void leisureSport() { System.out.println("도쿄타워 번지점프 투어"); } @Override public void sightseeing() { System.out.println("오사카 관람 투어"); } @Override public void food() { System.out.println("초밥 투어"); } } |
-JapanTour 클래스가 완성되면 TourGuide 객체는 간단하게 이 클래스와 관계를 맺을 수 있음
private Providable tour = new KoreaTour(); ↓ private Providable tour = new JapanTour(); |
-마치 부속품을 붙였다가 떼었다 하는 것처럼 클래스의 변경이 이루어짐. 이후의 코드는 어차피 tour 참조변수를 통해 이루어지게 되므로 tour가 가리키는 인스턴스만 변경하면 이후의 코드는 수정할 필요가 없음
-이처럼 인터페이스를 통해 클래스 간의 관계가 느슨해질수록 시스템의 변경에 유연하게 대처함
4)인터페이스와 다형성
-특정한 인터페이스를 구현한 인스턴스는 해당 인터페이스 타입의 참조변수로 참조가 가능함. 이렇게 하면 특정한 객체를 다양한 타입으로 선언하고 사용함
인터페이스명 참조변수이름 = new 클래스명(); |
자바개념정리
상속 | 기존에 존재하는 클래스를 물려받음 하나만 상속됨 상속이 안되는 경우: 1.다중상속 불가, 2.final이 붙은 경우x 자식 생성자에서 부모를 호출하면서 이루어진다. |
class Perents{ }
class Child extends Perents{ } 자식이 부모까지 확장(부모 클래스 멤버 상속) Child( ) { super( ); } |
|
사용하는이유? | 코드 재사용, 중복을 줄이기 위해 | cf) 생성자는 상속되지 않음 | |
오버라이딩
(overriding) |
리모델링
자식 클래스에서 부모 클래스로부터 물려받은 메서드를 다시 작성하는 것 |
||
this | 해당 클래스의 객체 | ||
this( ) | 클래스 생성자 this -> 클래스명으로 대체 가능 | ||
super | 부모 클래스 | ||
super( ) | 자식 생성자에서 부모 생성자를 호출할 때 사용 부모 클래스의 생성자 호출 |
자식 클래스 생성자 첫 줄 | |
생성자가 없을때 | 1.기본생성자 만들기: 클래스명 ( ) { } 2.자식 생성자 내부에 부모 클래스 생성자 super( ); 넣기 |
||
Object 클래스 | 모든 클래스의 조상인 클래스(최상위) -> 자동으로 상속 | ||
Package | 폴더(클래스를 모아놓은 일종의 집합) | 유지보수 및 관리하기 위해 | |
import | 수입 다른 패키지에 있는 클래스를 사용하고 싶을 때 클래스 이름 참조 |
import 패키지명.클래스명; | ex) import java.util.*; |
제어자 | 클래스나 멤버의 사용을 제어하기 위해 사용 | ||
접근 제어자 | 외부에서 접근하는 것을 막는 것 | 1.public: 제한x 클래스의 자식(변수, 함수) 2.protected: 같은 패키지 내, 자손 클래스 3.default: 같은 패키지 내, 생략 4.private: 같은 클래스 내 |
2,3 -> not visible 안보임
에러: 접근제어자 안만듬 *규칙: 접근제어자 상태 리턴타입 변수명 instance void a( ){ } 함수 => 이름앞에 3개 사용 static int a; 변수 |
private | 간접적으로 값에 접근 주로 변수에서 처리함 |
getter: get형식의 메서드 -> return;반환 setter: set형식의 메서드 -> 값 설정 |
|
final | final 변수: 값 변경 불가 final 메서드: 오버라이딩 불가 final 클래스: 상속불가 |
||
다형성 | 객체의 자료형을 변경 여러 형태의 인스턴스를 가짐 참조변수 하나로 여러 타입의 인스턴스를 참조 |
ex) a obj = new b(); (b클래스가 a를상속) | *toString() 함수: 자동으로 실행 |
추상 메서드 | 선언부만 정의하고 구체적인 내용은 비워놓은 메서드 상속받은 하위 클래스에서 반드시 구현 |
||
추상 클래스 | 추상 메서드를 멤버로 가지는 클래스 |
abstract void methodA(); '{ }' 중괄호 생략, 세미콜론' ;' 붙이기
|
|
인터페이스(Interface)
|
다중상속 |
interface 인터페이스이름{
public static final 타입 이름 = 값; => 상수 piblic abstract 반환타입 메서드이름(매개변수); => 추상메서드 } |
'프로그래밍 > java' 카테고리의 다른 글
JAVA 프로그래밍 50일차 (25/1/21) (0) | 2025.01.21 |
---|---|
JAVA 프로그래밍 49일차 (25/1/20) (2) | 2025.01.20 |
JAVA 프로그래밍 47일차 (25/1/16) (2) | 2025.01.16 |
JAVA 프로그래밍 46일차 (25/1/15) (0) | 2025.01.15 |
JAVA 프로그래밍 45일차 (25/1/14) (0) | 2025.01.14 |