/*
부모생성자호출(super call)
모든 객체는 클래스의 생성자를 호출해야만 생성이 된다. 부모 객체도 예외는 아니다.
그렇다면 부모객체를 생성하기 위해서는 자식 생성자에서 부모 생성자가 호출되어야 한다.
자식생성자에서 부모생성자를 호출할 경우에는 자식생성자의 ㅂ맨처음(첫줄)에 선언되고 호출되어야
한다.
부모생성자가 명시적으로 선언되지 않앗다면 컴파일에러가 발생된다. 자식객체는 부모클래스의 생성자와
동일한 시그니처를 갖는 부모생성자를 호출한다. 만약 매개값의
시그니처와 일치하는 부모생성자가 없을 경우에도 컴파일에러가 발생한다.
super(매개값...)가 생략되면 컴파일러는 부모의기본 생성자 super()가 자동으로 추가되기
때문에 부모클래스에 기본생성자가 반드시 존재해야 한다.
부모클래스에 기본생성자가 없고 일반생성자(매개값이 있는)가 있다면 자식생성자에서는
반드시 부모생성자를 호출하기 위해서 동일 시그니처를 갖는 super(매개값...)생성자를
명시적으로 호출해야 한다. 그리고 반드시 부모생성자의 호출은 자식생성자의 맨 첫줄에 위치해야 한다/.
*/
public class Student extends People{
int studentNo;
public Student() {
super(); // People의 기본 생성자를 호출
}
@Override
public String toString() {
return "Strudent [studentNo=" + studentNo + ", name=" + name + ", ssn=" + ssn + "]";
}
public Student(String name, String ssn, int studentNo) {
super(name,ssn);
this.studentNo = studentNo;
}
}
public class StudentMain {
public static void main(String[] args) {
Student student = new Student("홍길동","991118-1234567",1000);
System.out.println(student);
Student student2 = new Student();
student2.studentNo = 2000;
student2.name = "손흥민";
student2.ssn= "951212-1234567";
System.out.println(student2);
}
}
/*
메서드재정의(method override)
부모클래스의 모든 메서드가 자식 클래스에 맞게 설계되어 있다면 가장 이상적인 상속이지만
어떤 메서드는 자식클래스가 사용하기에는 적합하지 않을 수도 있다. 이런 경우에 상속된 일부
메서드는 자식클래스에서 다시 수정해서 사용해야 한다. Java는 이런 경우를 위해서 메서드의
오버라이드 기능을 제공한다.
메서드오버라이드는 상속된 메서드의 내용이 자식 클래스에 맞지 않을 경우 또는 자식 클래스에서
필요한 기능이 있을 경우에 자식 클래스에서 부모 클래스의 메서드 이름과 동일한 시그니처를 갖는
메서드를 재정의하는 것을 말한다.
부모 메서드가 오버라이드 되어 있다면 부모객체의 메서드는 숨겨지기 때문에 자식 객체에서 메서드를
호출하면 오버라이드된 자식 객체의 메서드가 호출된다.
메서드를 오버라이드할 경우에는 아래와 같은 규칙에 따라야 한다.
1. 부모메서드와 동일한 시그니처(리턴타입, 메서드명, 매개변수갯수와 타입)를 가져야 한다.
2. 접근제한을 부모 객체보다 더 강하게 정의할 수 없다.
3. 새로운 예외(Exception)를 던질(throw) 수 없다.
4.
*/
public class Calculator {
double areaCircle(double r) {
System.out.println("Calculator.areaCircle 메서드 실행");
return Math.PI * r * r;
}
}
public class Computer extends Calculator{
@Override
double areaCircle(double r) {
//return super.areaCircle(r);
System.out.println("Computer.areaCircle 메서드 실행");
return 3.14 * r * r;
}
}
public class ComputerMain {
public static void main(String[] args) {
int radius = 10;
System.out.println(Math.PI);
System.out.println();
Calculator calculator = new Calculator();
System.out.println("원의 면적= " + calculator.areaCircle(radius));
System.out.println();
Computer computer = new Computer();
System.out.println("원의 면적= " + calculator.areaCircle(radius));
System.out.println();
}
}
/*
타입변환과 다형성
다형성이란? 동일타입이지만 실행결과가 다양한 형태의 객체를 이용할 수 있는 성질을 말한다.
프로그램 측면에서 보면 다형성의 하나의 타입에 여러형태의 객체르 ㄹ대입함으로써 다양한 기능
을 수행할 수 있게 한다.
다형성을 위해서 Java는 자식클래스가 부모클래스로 타입변환을 허용한다. 즉, 부모타입에 모든
자식객체들을 대입할 수 있다는 것이다. 이 기능을 이용한다면 모든 객체는 부품화가 가능해 진다.
타입변환이란? 데이터타입을 다른 데이터타입으로 변환하는 행위를 말한다. 기본데이터타입의
변환처럼 참조타입(class, array, interface, enum)도 타입변환이 가능하다.
직접적인 상속관계가 있는 클래스사이에서만 타입변환이 가능하다.
자동타입변환(promotion)은 프로그램실행 도중에 자동적으로 타입변환이 일어나는 것을 말한다.
자동타입변환 개념은 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수
있다.
주의할 점은 자동타입변환이 된 후에는 부모클래스에 선언된 필드와 메서드만 접근이 가능하다.
비록 변수는 자식객체를 참조하지만 변수로 접근 가능한 멤버는 부모클래스의 멤버로만 제한된다.
그,러나 예외가 있는데 메서드가 자식클래스에서 오버라이딩이 되었다면 부모클래스의 메서드가
호출되는 것이 아니라 자식클래스의 메서드가 호출된다.
참조타입의 강제타입변환(Casting)
강제타입변환은 부모타입을 자식타입으로 변환하는 것을 말한다. 형변환이 된다고
해서 모든 부모타입이 자식타입으로 강제형변환할 수 있는 것은 아니다.
강제타입변환이 되는 경우는 자식타입이 부모타입으로 형변환이 된 후에 자식타입
으로 변환되는 경우에만 강제타입변환을 할 수가 있다.
자식 타입이 부모타입으로 자동형변환하면 부모타입에 선언된 필드와 메서드만 사용
할 수 있다. 자식타입이 부모타입으로 자종형변환이 되면 부모타입에서 선언된
필드와 메서드만 사용할 수 있다. 만약, 자식타입에 선언된 필드와 메서드를 꼭 사용해야 하는
경우에는 강제형변환을 해서 다시 자식타입으로 변환한 후에 자식타입의
필드와 메서드를 사용할 수 있다.
*/
public class Parent {
public String field1;
public void method1(){
System.out.println("Parent.method1() 호출");
}
public void method2(){
System.out.println("Parent.method2() 호출");
}
}
public class Child extends Parent{
public String field2;
@Override
public void method2() {
System.out.println("Child.method2() 호출");
}
public void method3() {
System.out.println("Child.method3() 호출");
}
}
public class CastingMain {
public static void main(String[] args) {
// 1. 자동형변환
Parent parent = new Child(); // 자동형변환
parent.field1 = "사용가능";
// parent.field2 = "사용불가"; //
parent.method1();
parent.method2(); // 사용할 수 있지만 child에서 재정의
// parent.method3(); // 사용불가
// 2. 강제형변환
// 1) 형변환불가
// 직접생성한 부모객체에서 자식객체로 형변환하는 경우는 불가
// 자식객체 -> 부모객체 -> (부모타입)자식객체의 순서로 형변환하는 것은 가능하지만
// 부모객체 -> (부모타입)자식객체로 직접 형변환 하는 것은 불가능
int val = (int) 1.0d; // 강제형변환
Parent parent2 = new Parent();
// 문법에러는 아니지만 ㅅ ㅣㄹ행시에 에러가 발생한다.
// java.lang.ClassCastException이 발생
// Child child = (Child) parent2;
// 2) 형변환가능
Child child = (Child) parent;
child.field1 = "사용가능";
child.field2 = "사용가능";
child.method1();
child.method2();
child.method3();
System.out.println();
System.out.println("parent2 = "+parent2.getClass());
System.out.println("parent = "+parent.getClass());
System.out.println("child = "+child.getClass());
System.out.println();
System.out.println(parent == child); // true
System.out.println(parent2 == child); // false. 일 경우에는 강제형변환하지 않도록 로직에 반영해야 한다.
}
}
/*
객체타입확인연산자(instanceof)
강제타입변환은 자식객체에서 부모객체로 타입변환이 되어 있는 상태에서만 가능하기 때문에
부모타입의 변수가 부모객체를 참조할경우 자식타입으로 변환할 수가 있다.
예를 들어
Parent parent = new Parent();
Child child = (Child)parent; <-강제형변환 불가, ClassCastException 발생
instanceof연산자는 좌측항은 객체가 오고 우측항은 타입이 오는데 좌측항의 객체가 우측항의
인스턴스(객체)가 아니면 false, 우측항의 타입으로 생성된 인스턴스(객체)라면 true를 리턴
boolean result = 객체 instanceof 참조타입;
instanceof 연산자는 매개값의 타입을 조사할 때 주로 사용한다. 매서드내에서 강제타입변환이
필요한 경우 반드시 매개값이 어떤 타입인지를 instanceof연산자로 확인하고 안전하게 강제타입변환을
해야 한다.
만약 타입을 확인하지 않고 강제타입변환을 시도할 경우에 강제타입변환이 되지 않을 경우에는
ClassCastException 예외가 발생한다.
*/
public class InstanceofMain {
public static void main(String[] args) {
// 강제변환불가
// Parent parent = new Parent();
// Child child = (Child) parent;
Parent parentA = new Child(); // 자동형변환
method1(parentA);
method2(parentA);
System.out.println();
Parent parentB = new Parent();
method1(parentB);
}
private static void method1(Parent instance) {
System.out.println(instance.getClass());
if(instance instanceof Child) {
Child child = (Child) instance;
System.out.println("method1()-강제형변환 성공");
}else {
System.out.println("method1()-강제형변환 실패");
}
}
private static void method2(Parent instance) {
System.out.println(instance.getClass());
Child child = (Child) instance;
System.out.println("method2()-강제형변환 성공");
}
}
/*
추상클래스
1. 추상클래스의 개념
사전적인 의미로는 추상은 실체간에 공통된 특성을 추출(선언)한 것을 말한다.
예를 들어 새, 곤충, 물고기 등의 실체에서 공통된 특성을 추출해 보면 동물이라는
공통점이 있다. 이와같이 구체적인 실체라기보다는 실체들의 공통된 특성을 가지고 있는 것을 추상적인
것이라고 볼 수 있다.
클래스에서도 추상클래스를 정의할 수 있다. 객체를 직접 생성할 수 있는 클래스를 실체
클래스라고 한다면 이 실체 클래스의 공통된 특성을 추출해서 선언한 클래스를 추상클래스
라고 한다.
추상클래스와 실체클래스는 상속관계를 가지고 있다. 추상클래스가 부모클래스이고 실체클래스가
자식클래스로 구현되어 실체클래스는 추상클래스의 모든 특성을 상속받고 또한 실체
클래스에서 추가적인 특성을 가질 수 가 있다. 여기서 특성이란 필드와 메서드를 말한다.
추상클래스는 실체클래스의 공통되는 필드와 메서드를 추출해서 만들었기 때문에
추상클래스로 객체를 직접 생성할 수가 없다. 다시말해서 추상클래스는 new 연산자를 사용해서 겍체
(인스턴스)를생성할 수가 없다.
2. 추상클래스의 용도
1) 실체클래스의 공통된 필드와 메서드의 이름을 통일(공통사용)할 목적
2) 실체클래스를 작성할 때 개발 시간을 단축
3. 추상클래스의 선언
추상클래스는 실체 클래스가 공통적으로 가져야 할 필드와 메서드를 정리해 놓은 추상적인
클래스이므로 실체 클래스의 멤버(필드, 메서드)를 통일화 하는데 목적이 있다.
모든 실체들이 가지고 있는 메서드의 실행내용이 동일하다면 추상클래스에 메서드를 작성
한느 것이 좋을 것이지만 메서드의 선언만 통일화하고 실체 실행내용을 실체 클래스마다
달라야 하는 경우가 있다.
예를 들어 Animal이라는 추상클래스에서 sound()라는 메서드를 정의한 후이 cat, dog, bird
즉, Animal 추상클래스를 상속받은 실체클래스에서 각각의 실체의 특성에 맞게 메서드를
작성하고 sound()라는 메서드는 실체 클래스에서 반드시 구현되도록 하기 위해서
추상메서드로 선언하고 그 추상메서드를 상속받는 실체 클래스에서 실제로 실행할 메서드를 구현하도록\
한다.
*/
public abstract class Phone {
// 필드
public String owner;
// 생성자
public Phone(String owner) {
this.owner = owner;
}
// 메서드
public void powerOn() {System.out.println("파워온");}
public void powerOff() {System.out.println("파워오프");}
}
public class SmartPhone extends Phone {
public SmartPhone(String owner) {
super(owner);
}
public void internetSearch(String url) {
System.out.println(url + "에서 검색을 합니다");
}
}
public class SmartPhoneMain {
public static void main(String[] args) {
//추상클래스는 객체를 생성할 수 없다.
//Phone phone = new Phone();
SmartPhone phone = new SmartPhone("홍길동");
System.out.println(phone.owner);
phone.powerOn();
phone.internetSearch("www.google.com");
}
}
'일 > JAVA' 카테고리의 다른 글
java08.nested (0) | 2023.05.25 |
---|---|
java07.interface (0) | 2023.05.25 |
java05.class.package (0) | 2023.05.24 |
java05.class.method (2) | 2023.05.24 |
java05.class.member (0) | 2023.05.24 |