무결성
을 위함공용
public class 자식클래스 extends 부모클래스{
}
public class 자식클래스 extends 부모클래스1, 부모클래스2{
}
package day0621.Inheritance;
public class Phone
{
//필드 선언
public String model;
public String color;
//메소드 선언
public void bell() {
System.out.println("벨이 울립니다.");
}
public void sendVoice(String message) {
System.out.println("본인: "+message);
}
public void receiverVoice(String message) {
System.out.println("상대방: "+message);
}
public void hangUp() {
System.out.println("전화를 끊습니다. 통화 종료!");
}
}
public class SmartPhone extends Phone //다형성
{
public boolean wifi;
public SmartPhone(String model, String color) {
super(); //생략가능 나의 부모 생성자를 호출 => 부모가 먼저 만들어짐
this.model = model;
this.color=color; //Phone으로부터 상속받은 필드를 내것처럼 사용
}
public void setWifi(boolean wifi) {
this.wifi = wifi;
System.out.println("와이파이 상대를 변경했습니다.");
}
public void internet() {
}
}
**public class SmartPhoneEX
{
public static void main(String[] args)
{
//SmartPhone 객체 생성 model : 갤럭시 color :white
SmartPhone myPhone = new SmartPhone("갤럭시", "white");
//Phone로부터 상속받은 필드 읽기 출력
System.out.println(myPhone.model);
System.out.println(myPhone.model);
//SmartPhone의 필드 읽기 출력
System.out.println(myPhone.wifi);
// Phone으로부터 상속받은 전체 메소드 호출
myPhone.bell();
myPhone.sendVoice("안녕하세요");
myPhone.receiverVoice("안녕 나는 누구게?");
myPhone.sendVoice("근데 나 바쁘니까 좀이따 전화할게 끊어!");
myPhone.hangUp();
//SmarPhone의 메소드 호출
myPhone.setWifi(true);
myPhone.internet();
}
}**
자식클래스 변수 = new 자식클래스();
super()
에 의해 호출// 자식 생성자 선언
public 자식클래스(){
super();
}
super()
일 때 : 모의 생성자를 호출하는 특수 메소드class Phone
{
//필드 선언
public String model;
public String color;
public Phone() {
System.out.println("Phone() 생성자 실행");
}
public Phone(String model, String color) {
System.out.println("SmartPhone(String model, String color)생성자 실행 완료!");
}
}
class SmartPhone extends Phone //다형성
{
public boolean wifi;
public SmartPhone(String model, String color) {
//super(); //생략가능 (컴파일시 자동 추가) => 부모의 생성자를 호출하는 특수 메소드
// => 이로 인해 Phone() 생성자 실행 출력
super();
this.model = model;
this.color=color; //Phone으로부터 상속받은 필드를 내것처럼 사용
System.out.println("SmartPhone(String model, String color)생성자 실행 완료!");
}
}
class SmartPhoneEX
{
public static void main(String[] args)
{
// SmartPhone 객체 생성 model : 갤럭시 color :white
SmartPhone myPhone = new SmartPhone("갤럭시", "white");
//Phone으로부터 상속받은 필드 입력 출력
System.out.println(myPhone.model);
System.out.println(myPhone.color);
}
}
위의 코드에서 SmartPhone class만 변경
this.model = model
해주지 않아도 됨
class SmartPhone extends Phone //다형성
{
public boolean wifi;
public SmartPhone(String model, String color) {
super(model, color);
System.out.println("SmartPhone(String model, String color)생성자 실행 완료!");
}
}
선언부(리턴 타입, 메소드 이름, 매개변수)
와 동일해야 함super 키워드
와 도트(.) 연산자
를 사용하면 숨겨진 부모 메소드를 호출public class Calculator
{
static final double PI = 3.14;
public double areaCircle(double r) {
System.out.println("Calculator의 areaCircle() 실행");
return r*r*PI;
}
}
public class Computer extends Calculator
{
// 메소드 오버라이딩
@Override // 컴파일 단계에서 정확히 오버라이딩이 되었는지 체크 해줌
public double areaCircle(double r) {
double result=super.areaCircle(r); //super(); 부모의 생성자 호출
System.out.println("부모의 areaCircle()실행"+result);
System.out.println("Computer의 areaCircle() 실행");
return r*r*Math.PI;
}
}
public class ComputerEx
{
public static void main(String[] args) {
Calculator cal = new Calculator();
System.out.println(cal.areaCircle(5.5));
Computer cal1 = new Computer();
System.out.println(cal1.areaCircle(5.5));
}
}
부모 클래스
class Drink{
String name;
int price;
int count;
public Drink() {}
public Drink(String name, int price, int count) {
this.name = name;
this.price = price;
this.count = count;
}
public int getTotalPrice() {
int totalPrice = this.price * this.count;
return totalPrice;
}
public static void printTitle() {
System.out.printf("%8s%8s%8s%8s%n","상품명","단가","수량","금액");
}
public void printData() {
System.out.printf("%8s%8d%8d%d%n",name,price,count,getTotalPrice());
}
}
자식 클래스
super(name, price, count)
; : 부모클래스 꺼 사용class Alcohol extends Drink{
double alcper;
public Alcohol(){}
public Alcohol(String name, int price, int count,double alcper) {
this.name = name;
this.price = price;
this.count = count; // 위 3개 대신 super(name, price, count); 가능
this.alcper = alcper;
}
public static void printTitle()
{
System.out.printf("%8s%8s%8s%-3s%n","상품명(도수[%])","단가","수량","금액");
}
@Override
public void printData()
{
System.out.printf("%s %d %d %d%n",name+"("+alcper+")",price,count,getTotalPrice());
}
실행 클래스 : Prob1
public class Prob1
{
public static void main(String[] args)
{
Drink coffee = new Drink("커피", 1500, 4);
Drink tea = new Drink("녹차", 1100, 7);
Alcohol wine = new Alcohol("와인", 5000, 3, 15.1);
System.out.println("***** 매 출 전 표 ***** ");
Drink.printTitle();
coffee.printData();
tea.printData();
System.out.println();
Alcohol.printTitle();
wine.printData();
int sum = coffee.getTotalPrice() + tea.getTotalPrice() + wine.getTotalPrice();
System.out.println();
System.out.println("*** 총금액 " + sum + "원 ***");
}
}
final 키워드
를 붙이면 오버라이딩할 수 없음부모 클래스에 선언된 final 메소드
는 자식protected
는 상속과 관련이 있고, public과 default의 중간쯤에 해당하는 접근 제한default처럼
접근이 가능하나, 다른 패키지에서는 자식 클래스만 접근
을 허용부모타입 변수 = 자식타입객체;
public class Parent
{
public void method1() {
System.out.println("Parent-method1()");
}
public void method2() {
System.out.println("Parent-method2()");
}
}
public class Child extends Parent
{
@Override
public void method2()
{
System.out.println("Child-method2()");
}
public void method3()
{
System.out.println("Child-method3()");
}
}
public class ChildEx
{
public static void main(String[] args)
{
// 자식 객체 생성
Child child = new Child();
// 부모로 자식을 자동타입 변환
Parent parent = child;
parent.method1();
parent.method2(); //자식이 재정의해서 자식의 method2()를 호출 Child-method2()
//parent.method3() : 부모는 자식꺼의 메소드를 가져올 수 없음 Parent parent = child;이기에 가져올 수 없다.
}
}
자식 타입 변수 = (자식타입) 부모타입객체;
부모 타입
에 선언된 필드와 메소드만 사용 가능public class Parent
{
String field1;
public void method1() {
System.out.println("Parent-method1()");
}
public void method2() {
System.out.println("Parent-method2()");
}
}
public class Child extends Parent
{
String field1;
String field2;
@Override
public void method2()
{
System.out.println("Child-method2()");
}
public void method3()
{
System.out.println("Child-method3()");
}
}
public class ChildEx
{
public static void main(String[] args)
{
// 자식 객체 생성
Child child = new Child();
// 1. 먼저 Parent 공간이 생김. m1, m2를 가지고 있음
// 2. 자식을 담을려고 보니.... 자식이 더 커서 자식만 가지고 있는 메서드 같은건 담지 못함
Parent parent = new Child();
System.out.println(parent.field1);
parent.method1();
parent.method2();
// parent.field2; // 접근 불가능 => 자식에만 있는 필드이기 때문에
// 만약... 접근 가능하게 하고 싶다면..자식으로 강제형 변환을 통해 접근 가능하도록
Child child1 = (Child)parent;
child1.field2="data2";
child1.method3();
// 부모로 자식을 자동타입 변환
// Parent parent = child;
parent.method1();
parent.method2(); //자식이 재정의해서 자식의 method2()를 호출 Child-method2()
//parent.method3() : 에부모는 자식꺼의 메소드를 가져올 수 없음 Parent parent = child;이기에 가져올 수 없다.
}
}
자동 타입 변환 + 메소드 재정의
대입되는 객체가 달라져서
실행 결과가 다양하게 나올 수 있는 것public class Tire
{
public void roll() {
System.out.println("Tire");
}
}
public class HankookTire extends Tire
{
public void roll()
{
System.out.println("HankbookTire");
}
}
public class KumhoTire extends Tire
{
public void roll() {
System.out.println("KumhoTire");
}
}
public class Car
{
public Tire tire;
public void run() {
tire.roll();
}
}
public class CarEx
{
public static void main(String[] args)
{
Car mycar = new Car();
mycar.tire = new Tire(); //타이어를 낌
mycar.run(); //달리기
mycar.tire = new KumhoTire(); //타이어를 바꿔낌
mycar.run();
mycar.tire = new HankookTire(); //타이어를 바꿔낌
mycar.run();
}
}
어떤 자식 객체가 제공되느냐
에 따라서 메소드의 실행 결과가 달라짐**class Vehicle{
public void run() {
System.out.println("차량이 달립니다.");
}
}
class Bus extends Vehicle{
@Override
public void run()
{
System.out.println("qjtmrk 달립니다.");
}
}
class Taxi extends Vehicle{
@Override
public void run()
{
System.out.println("택시가 달립니다.");
}
}
class Driver{
public void drive(Vehicle v) { //클래스 타입의 매개변수를 전달받는다.
v.run();
}
}
public class DriverEx
{
public static void main(String[] args) {
// 1. 운전자 객체 생성
Driver driver = new Driver();
//2. 운전자에게 버스객체를 전달 => 버스를 운전한다.
Bus bus = new Bus();
if(bus instanceof Vehicle ) { //자동타입변환이 되기 때문에 Vehicle 사용 가능
driver.drive(bus);
}
// 3. 운전자에게 택시객체를 전달 => 택시를 운전한다.
Taxi taxi = new Taxi();
driver.drive(taxi);
if(taxi instanceof Vehicle ) { //자동타입변환이 되기 때문에 Vehicle 사용 가능
driver.drive(taxi);
}
}
}**
class Person{
public String name;
//생성자
public Person() {}
//name을 받아서 초기화시키는 생성자 선언
Person(String name) {
this.name=name;
}
public void walk(){
System.out.println("걷습니다.");
}
}
class Student extends Person{
public int stuNo;
Student(){};
// 학생 이름과 학생번호를 전달받아 초기화하는 생성자
Student(String name, int no){
super(name);
this.stuNo=no;
}
public void study() {
System.out.println("공부를 합니다.");
}
}
public class InstanceOfEx
{
public static void personInfo(Person person) {
//person객체인지 student 객체인지 비교하는 것 찾기
System.out.println("name ; "+person.name);
person.walk();
//person이 참조하는 객체가 Student 타입인지 확인
if(person instanceof Student student) {
System.out.println("stuNo : "+student.stuNo);
student.study();
}
}
public static void main(String[] args)
{
//Person객체를 매개값으로 제공하고 personInfo() 호출한다.
Person p1 = new Person("김홍도");
personInfo(p1); //같은 static 타입이라 바로 부를 수 있음
Person p2 = new Student("김길동",10);
personInfo(p2);
}
}
instanceof
연산자에서 좌항의 객체가 우항의 타입이면 true를 산출하고 그렇지 않으면 false를 산출boolean result = 객체 instanceof 타
abstract
: 실체 간에 공통적인 특성
을 추출한 것abstract
키워드를 붙임사용 불가한 코드
Animal animal = new Animal();
사용 가능한 코드
실행 내용
은 자식 클래스마다 달라야 하는 경우 추상 메소드를 선언할 수 있음abstract class Animal{
public void breathe() {
System.out.println("숨을 쉽니다.");
}
public void eat() {
System.out.println("먹습니다.");
}
public abstract void sound(); //{body}가 없는 추상메소드
}
//추상클래스를 상속할 때, 추상클래스 안에 추상메소드가 있다면 자식클래스에서는 반드시 추상메소드를 정의해줘야 함
class Dog extends Animal{
@Override
public void sound()
{
System.out.println("멍멍");
}
}
class Cat extends Animal{
@Override
public void sound()
{
System.out.println("냥냥");
}
}
public class AbstractEx
{
public static void main(String[] args)
{
Dog dog = new Dog();
dog.sound();
dog.breathe();
dog.eat();
Cat cat = new Cat();
cat.breathe();
cat.sound();
cat.eat();
System.out.println("=============");
animalSound(dog);
animalSound(cat);
}
public static void animalSound(Animal animal) {
animal.sound();
} //전달받은 동물의 타입에 맞추어 소리를 내는
}
abstract class Shape{
protected double area;
private String name;
public Shape() {
}
public Shape(String name) {
this.name = name;
}
abstract void calculationArea();
public void print(){
System.out.println(this.name +"이고 면적은 "+ area+ "입니다." );
}
/**
* @return the name
*/
public String getName()
{
return name;
}
/**
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
}
class Circle extends Shape{
Circle c;
private double radius;
public Circle(){}
public Circle(double r) {
this.radius = r;
}
public Circle(String name,double r) {
super(name);
this.radius = r;
}
@Override
void calculationArea() {
double area = radius * radius * Math.PI;
super.area = area;
}
/**
* @return the radius
*/
public double getRadius()
{
return radius;
}
/**
* @param radius the radius to set
*/
public void setRadius(double radius)
{
this.radius = radius;
}
}
class Rectangular extends Shape{
private double width;
private String height;
public Rectangular(){}
public Rectangular(String name, double width, String height) {
super(name);
this.width = width;
this.height=height;
}
@Override
void calculationArea() {
double area = width * Integer.parseInt(height);
super.area = area;
}
}
public class ShapeEx
{
public static void main(String[] args)
{
Circle circle = new Circle("원", 5);
circle.calculationArea();
circle.print();
Rectangular rect = new Rectangular("직사각형", 100,"2");
rect.calculationArea();
rect.print();
}
}