-
java 클래스대학/객체지향프로그래밍 2022. 10. 9. 12:02
- 메서드 오버로딩(method overloading)
class OverloadDemo { void test() { System.out.println("No parameters"); } void test(int a, int b) { System.out.println("a: " + a + "b: " + b); } double test(double a) { System.out.println("double a: " + a); return a*a; } }
같은 이름의 메서드를 사용해도 호출하는 인자값에 따라 다른 메서드를 호출하게 된다.
- 인자 전달 방식
1. Call by Value (값에 의한 호출)
인자가 기초타입인 경우 값에 의한 호출을 사용하게 된다. (byte, int, float ...)
이 호출방식의 경우 인자로 넘겨준 본래 변수의 값은 메서드 내에서 어떤 짓을 벌여도 값이 변하지 않는다.
2. Call by Reference (참조에 의한 호출)
인자가 객체인 경우 참조에 의한 호출을 사용하게 된다. (클래스의 인스턴스 객체 ...)
이 호출방식의 경우 인자로 넘겨준 본래 변수의 값은 메서드 내에서 값을 변경할 경우 본래 변수도 값이 변하게 된다.
class Test { int a, b; Test(int a, int b) { this.a = a; this.b = b; } void add10(Test o) { o.a += 10; o.b += 10; } static void add10(int a, int b) { a += 10; b += 10; } } public class App { public static void main(String[] args) { Test o = new Test(10, 20); int a = 10, b = 20; o.add10(o); // Call by Reference System.out.println("o.a: " + o.a + ", o.b: " + o.b); // 1 Test.add10(a, b); // Call by Value System.out.println("a: " + a + ", b: " + b); // 2 } }
1 에서는 값이 20, 30으로 10씩 증가 되었지만,
2 에서는 값이 10, 20으로 증가되지 않았다.
- 키워드
1. 접근 제어자
public: 어느 클래스에서건 접근 가능
private: 클래스 멤버만 접근 가능 (캡슐화의 완성! getter, setter 메서드를 구현 해줘야 함)
protected: 클래스 멤버, 상속된 클래스 멤버만 접근 가능
(default): 패키지 멤버만 접근 가능 (동일한 폴더 내에서만 접근 가능)
2. static
static 변수: 클래스 로드시 변수가 초기화 되어, 동일한 클래스의 인스턴스라면 같은 변수를 공유하게 된다.
static 메서드(): 클래스 내부의 static 변수, 메서드만 접근할 수 있고, this 키워드를 사용할 수 없다.
static 키워드가 붙으면 컴파일 타임에 초기화 되기 때문에 동적으로 초기화되는 일반 변수, 메서드는 초기화되지 않아 접근할 수 없는 것.
따라서 static 키워드가 붙어 있으면 인스턴스 생성 없이 호출 가능하다.
3. final
const 키워드와 유사한 기능을 수행하여, 초기화 후에는 값 변경이 불가능하다.
- 상속(inheritance)
class SuperClass { protected int a; SuperClass(int a) { this.a = a; } void supPrint() { System.out.println("a: " + a); } } class SubClass extends SuperClass { private int b; SubClass(int a, int b) { super(a); this.b = b; } void subPrint() { System.out.println("a: " + a + ", b: " + b); } } public class App { public static void main(String[] args) { SuperClass sup = new SuperClass(10); sup.supPrint(); sup = new SubClass(11, 21); sup.supPrint(); // sup.subPrint(); SubClass sub = new SubClass(10, 20); sub.subPrint(); } } 실행 결과 a: 10 a: 11 a: 10, b: 20
자식 클래스는 extends 키워드를 이용해서 부모 클래스를 상속 받을 수 있다.
단, final 키워드가 붙은 클래스는 상속할 수 없다.
자식 클래스는 private 접근 제어가 걸린 부모 클래스의 멤버를 제외하고 모든 멤버에 접근할 수 있다.
정확하게 특정하고 싶으면 super 키워드를 사용하면 된다.
super.i: 부모의 i
this.i: 본인의 i
i: 인자로 들어온 i를 포함한 모든 i
부모 클래스의 참조자로 자식 클래스의 인스턴스를 참조할 수 있다.
단, 자식 클래스에서 새로 정의된 멤버에는 접근할 수 없다.
class A { A() { System.out.println("A"); } } class B extends A { B() { // super(); System.out.println("B"); } } class C extends B { C() { // super(); System.out.println("C"); } } public class App { public static void main(String[] args) { B c = new C(); } } 실행 결과 A B C
이처럼 다단계 상속도 가능하다.
단, 생성자의 호출 순서는 가장 부모인 클래스부터 호출된다.
- 메서드 오버라이딩(method overriding)
오버로딩은 같은 클래스 내에 동일한 이름에 다른 타입 또는 다른 인자가 들어올 때 사용할 수 있는 기법인 반면,
오버라이딩은 상속관계에 있어 이름, 타입, 인자까지 모두 동일할 때 사용할 수 있는 기법이다.
단, final 키워드가 붙은 메서드는 오버라이딩 할 수 없다.
오버라이딩 할 수 없는 대신 런타임에 오버라이딩 검사를 하지 않기 때문에 성능상의 이점을 가져갈 수 있다.
class SuperClass { int a; SuperClass() { a = 10; } void print() { System.out.println("a: " + a); } } class SubClass extends SuperClass { int b; SubClass() { super.a = 15; b = 20; } void print() { System.out.println("a: " + a + ", b: " + b); } void dPrint() { super.print(); print(); } } public class App { public static void main(String[] args) { SuperClass sup = new SuperClass(); sup.print(); // dynamic method dispatch sup = new SubClass(); sup.print(); // dynamic method dispatch // sup.dPrint(); SubClass sub = new SubClass(); sub.print(); sub.dPrint(); } } 실행 결과 a: 10 a: 15, b: 20 a: 15, b: 20 a: 15 a: 15, b: 20
위 처럼 print를 오버라이딩하면 동일한 메서드라도, 인스턴스에 따라 다른 출력값이 나오게 된다.
다만, 부모 클래스의 오버라이딩 전의 메서드를 사용해야 한다면 앞에 super 키워드를 붙여주면 된다.
동일한 참조자라도, 런타임에 호출할 메서드를 선택하는 방법을 동적 메서드 디스패치(dynamic method dispatch) 라고 한다.
- 추상 클래스(abstract class)
abstract class AbsClass { abstract void absPrint(); void print() { System.out.println("Already Implemented"); } } class SubClass extends AbsClass { void absPrint() { System.out.println("Implement"); } } public class App { public static void main(String[] args) { AbsClass c = new SubClass(); c.absPrint(); c.print(); } } 실행 결과 Implement Already Implemented
abstract 키워드를 이용해서 구조만 선언할 수 있다.
하지만, 구조 뿐만 아니라 필요한 기능은 미리 구현해 놓을 수도 있다.
도형의 넓이같이 상속한 대상에 따라 다르게 구현해야 하는 경우에 추상 클래스가 유용하다.
단, 추상 클래스는 인스턴스화 할 수 없다.
하지만, 추상 클래스 변수로 자식 클래스 인스턴스를 참조할 수는 있다.
- Object class
모든 클래스가 상속받는 java의 기본 클래스.
오브젝트를 다룰 때 유용한 메서드를 제공하고, 일부를 제외한 메서드는 오버라이딩 가능하다.
boolean equals(Object object); // 오브젝트가 같은지 검사 String toString(); // 오브젝트를 설명하는 문자열 반환
'대학 > 객체지향프로그래밍' 카테고리의 다른 글
java 인터페이스 (0) 2022.10.09 java 패키지 (0) 2022.10.09 java 연산 및 제어 (0) 2022.10.07 java 기본 문법 (0) 2022.10.07 java 특징 (0) 2022.10.07