본문 바로가기
PROGRAMING📚/Java📑

Java::확장-extends(상속)

Ta이니 2024. 6. 25.
728x90
반응형

객체의 확장

클래스의 인스턴스인지를 확인하는 연산

Member m1 = new Member("LGH", "010-3446-5555");
System.out.println(m1 instanceof Object);

//모든 클래스는 Object를 상속 받는다
// extends Object 안써두 됨
//상속 할 경우에는 Memeber 변수와 method 만 상속
class Member extends Object {
  String name, mobile;

  public String toString() {
    return String.format("Name : %s , Mobile : %s", name, mobile);
  }

  public Member(String name, String mobile) {
    this.name = name;
    this.mobile = mobile;
  }
}

 

상속 관계(has -a / is-a)

 

has- a 관계

Car는 Engine을 가지고 있을 뿐이지, car와 engine은 공통된 속성과 기능을 가지지 않음(비공유)

//has-a 관계
class Car {
  Engine engine = new Engine();
}

class Engine {
 int gitong;
}

 

is - a 관계

parent와 chile는 공통된 속성과 기능을 공유한다

//is-a 관계
class Parent {
  String familyName;

}

class Child extends Parent {

}

 

자바에서는 다중상속 허용하지 않음(명확하지 않을 수 있기 때문에) - 단일 상속

class SmartPhone extends Phone, Computer {  } //에러 발생(사용불가)

 

상속은 멤버변수와 메서드만 전달이 가능하다

 

추상클래스는 스스로 인스턴스 생성 불가능함

상속 받은 후 인스턴스 생성이 가능하다

package p05_Inherit;

public class Ex03extentds {
  public static void main(String[] args) {
    Marin m1 = new Marin();
    System.out.println(m1.hp);
  }
}

//abstract 추상적인 클래스
abstract class Unit {
  public Unit(){
    //this(), super()는 항상위(맨첫줄)에 있어야 하기 떄문에 두개를 동시에 사용이 불가능하다
    super();
    //this("","",15);
    System.out.println("야생 동물 생성");
  }
  public Unit(String tribe){
    super();
    this.tribe = tribe;
  }
  int hp;
  String tribe;

  public void mov(int x, int y) {
  }

  public void stop() {
  }
}

//abstract 를 사용하면 new/인스턴스 를 사용하지 못함
abstract class Terran extends Unit {
  //상속 할 경우에는 Memeber 변수와 method 만 상속
  public Terran(String uName, int hp) {
    //첫줄에 " super() = 부모를 가리킴 "가 숨어있음
    super("Terran",uName,hp); //Unit을 가리키고 있음
  }
}
class Marin extends Terran {
  public Marin() {
    super("Marin",60);
  }
}
class Medic extends Terran {
  public Medic() {
    super("Medic",45);
  }
}

 

this(), super()는 항상위(맨첫줄)에 있어야 하기 떄문에 두개를 동시에 사용이 불가능하다

public Unit(){
  super();
  System.out.println("야생 동물 생성");
}
public Unit(){
  this("","",15);
  System.out.println("야생 동물 생성");
}

상속관계의 형변환

public class Ex04Casting {
  public static void main(String[] args) {
    Father f1= new Father();
    Son s1= new Son();
    s1.hard();
    //상속관계의 형변환
    Father f2 = new Son();//자식 -> 부모 형변환이 일어나서 가능함
    //Son s2 = new Father(); //부모 -> 자식 Error :: s2 >= f2
    //Son s2 = (Son)new Father(); //실행 시 ,Error :: s2 >= f2
    Son s3  = (Son)f2; //자식 -> 부모 -> 자식
  }
}

 

상속관계의 형변환에서 변수와 메서드의 중복이 일어나는 경우

변수는 형변환 된, 타입의 값을 가진다

메서드는 무조건 자식의 메서드를 따른다

속성값은 부모의 값을 가짐

f2.hard();
System.out.println(f2.age);
s3.hard();
System.out.println(s3.age);

public class Ex04CastingReason {
  public static void main(String[] args) {
    Buyer person = new Buyer();
    person.money =1000;
    Tv tv = new Tv();
    Laptop laptop = new Laptop();
    Audio audio = new Audio();

    person.Buyer_Buy(tv.price);
    System.out.printf("남은돈 1: %d \n",person.money);
    person.Buyer_Buy(laptop.price);
    System.out.printf("남은돈 2: %d \n",person.money);
    person.Buyer_Buy(audio.price);
    System.out.printf("남은돈 3: %d \n",person.money);
  }
}
class Buyer{
  int money;
  int Buyer_Buy(int price){
    return money -= price;
  }
}
class Tv{
  int price=20;
  }
}
class Laptop {
  int price=30;
  }
}
class Audio {
  int price=40;
}

 

오버라이드(Override)  : 재정의

package p05_Inherit;

import java.util.Objects;

public class Ex05Override {
  public static void main(String[] args) {
    Data d1 = new Data(1);
    Data d2 = new Data(1);
    System.out.println(d1);
    System.out.println(d2);
    //주소값이 같아서 ,출력되지 않음 => 숫자를 비교함
    if (d1 == d2) {
      System.out.println("같다");
    }
    //equals를 재정의 해주어야함
    if (d1.equals(d2)) {
      System.out.println("같다");
    }
  }
}

class Data {
  int value;

  public Data(int value) {
    this.value = value;
  }

  @Override
  public String toString() {
    return "value : " + value;
  }

  //  @Override // 생략 가능
  public boolean equals(Object obj) {
    if (obj instanceof Data) {
      Data d = (Data) obj;
      return value == d.value;
    }
    return false;
  }

  @Override
  public int hashCode() {
    //hashCode의 값이 동일할 때
    return Objects.hash(value);
  }
}

 

Interface

 

java에서는 다중상속이 안된다. 그래서, interface를 사용한다
앞에 i 를 붙이거나 끝에able을 붙이면서 interface를 사용하겠다는 의미이다  -> 약속

 

class Hydra implements AttackAirable, AttackGroundable {
  @Override
  public void attack() {

  }
}

interface AttackAirable {
  //추상메서드와 상수만 정의(static, default 메서드 추가)
  public abstract void attack();
}

interface AttackGroundable {
  void attack();
}

정의 해주지 않으면 다음과 같이 빨간줄이 생김

 

interface의 중복된 상수는 static 이 붙어 있기 때문에 클래스와 함께 지정

static과 default 메서드만 선언이 가능함

@Override
public void attack() {
  //interface의 중복된 상수는 static 이 붙어 있기 때문에 클래스와 함께 지정
  System.out.println(AttackGroundable.Level);
}
interface AttackAirable {
  //추상메서드와 상수만 정의(static, default 메서드 추가)
  public abstract void attack();
  public static final  int Level =10;
}
interface AttackGroundable {
  void attack();
  void attackG();
  int Level =30;
}

 


 

참조형 타입의 형변환은 상속관계일 때, interface 일 경우 적용

객체지향 언너의 특징중 하나인 다형성(Polymorphism)

package p05_Inherit;

import common.Utils;

import java.util.Objects;

public class Ex08InterfaceCasting {
  public static void main(String[] args) {
    Mammals[] mammals = {new Dog(), new Cat(), new Bat()};
    Birds[] birds = {new Chicken(), new Eagle(), new Parrot()};
    Flyable[] flyables = {new Bat(), new Eagle(), new Parrot()};
    IGround[] grounds = {new Dog(), new Cat(), new Chicken()};

  }
}

interface Flyable {

}

interface IGround {

}

class Birds {
}

class Parrot extends Birds implements Flyable {
}

class Eagle extends Birds implements Flyable {
}

class Chicken extends Birds implements IGround {
}

class Mammals {
}

class Dog extends Mammals implements IGround {
}

class Cat extends Mammals implements IGround {
}

class Bat extends Mammals implements Flyable {
}

Java Casting

1) 기본형

2) 참조형 (상속, Interface)

3) 기본형 <-> 참조형

Object obj =10; //기본형 -> 참조형으로 형변환
Utils.typeOf(obj); //Integer

추상클래스(Abstract)

 

package p05_Inherit;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Ex09Abstract {
  public static void main(String[] args) {
    //스스로 인스턴스  생성 불가 (추상클래스, interface)
    //Abstract abs = new Abstract();
    //Interface inter = new Interface();
    new MyFrame();
  }
}
//추상클래스 : 스스로 인터페이스를 못만듬
//abstract 공통(표준)으로 사용하기 위해 만듦. 인스턴스 생성 불가
abstract class Abstract {
  int num = 10;
  void general() {
  }
  //추상 메서드를 사용할 경우, 반드시 abstract 붙임
  abstract void special();
}
interface Interface {
}
class MyFrame extends JFrame {
  public MyFrame() throws HeadlessException {
    setSize(300, 200);
    setTitle("My Window");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setLayout(new FlowLayout());
    JButton jButton = new JButton("확인");
    jButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        System.out.println("Hello");
      }
    });
    add(jButton);
    setVisible(true);
  }
}

 

 


 

접근 제어자 (Access Modifier) : public , protected , default, private

 

클래스 public , default, final, abstract
메서드 all , final,(abstract, static = 재정의 불가)
멤버변수 all, final(상수), static 
지역변수 final, var

 

 

지역변수는 접근 제어자 사용 불가

 

public String publicVar;
protected String protectedVar;
String defaultVar;
private String privateVar;

 

메서드 앞에도 접근제어자 4가지 다 사용이 가능하다

default 접근제어자는 패키지 안에서만 사용이 가능하다

final이 class 앞에 붙을 때 제어자는 상속이 안된다

 

protected는 패키지 안에서도 사용이 가능하지만 상속이 된 곳에서만 사용이 가능하다

다른 패키지 안에서 public 제어자 빼고 사용 불가능
상속을 받은 경우에만 사용이 가능하다

상속을 받을 값을 변수에 담아서 사용해야함

public class Ex10protected extends Ex10Modifier {
  String str = protectedVar;
  Ex10Modifier ex10Modifier = new Ex10Modifier();
  void done(){
    System.out.println(ex10Modifier.publicVar);
    System.out.println(str);
    //System.out.println(ex10Modifier.defaultVar);
    //System.out.println(ex10Modifier.privateVar);
  }
}

 


 

지역 변수를 익명객체에서 쓸 때, final 붙인다

(java 8 부터 안 붙여도 됨)

final 이 붙은 지역변수는 변경 불가능하다

 

  public static void main(String[] args) {

    final int result = 10;//final이 붙은 지역변수는 변경불가
    new JButton().addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        System.out.println(result); //상수라서 사용은 가능하지만
//      result =10;  //지역변수는 익명객체에서 변경이 불가능하다
      }
    });

 

 

지역변수는 익명객체에서 변경이 불가능하다


Java 10 부터 var 생김

지역변수 일 때, 동적할당이 가능하다

var name ="LGH";
Utils.typeOf(name);

선언과 동시에 초기화 분리 적용은 되지 않는다

 


싱글톤(Singleton)

 

 

package p05_Inherit;

public class Ex11Singleton {
  public static void main(String[] args) {
    Singleton s1 = new Singleton();
    Singleton s2 = new Singleton();
    System.out.println(s1);
    System.out.println(s2);
  }
}
//인스턴스를 하나만 사용 할수 있게 만들고 싶음
class Singleton{ }

인스턴스로 생성되면서 주소값이 다르게 생성됨

 

인스턴스를 하나만 사용할 수 있도록 만들기 위해서

'싱글톤' 을 사용한다

동일한 주소값을 사용

package p05_Inherit;

public class Ex11Singleton {
  public static void main(String[] args) {
    Singleton s1 = Singleton.getInstance();
    //Singleton s2 = new Singleton();
    System.out.println(s1);
    //System.out.println(s2);
  }
}
//인스턴스를 하나만 사용 할수 있게 만들고 싶음
class Singleton{
  private static Singleton singleton;
  private Singleton() {
  }
  static public Singleton getInstance(){
    if(singleton == null){
      singleton = new Singleton();
    }
    return singleton;
  }
}

클래스 내부 값 가져오기?

package p05_Inherit;

public class Ex12Inner {
  public static void main(String[] args) {
    Outer outer = new Outer();
    Outer.Inner oi = new Outer().new Inner();
    System.out.println(oi.iv);
    //static
    Outer.InnerStatic ois = new Outer.InnerStatic();
    System.out.println(ois.isv);
  }
}
class Outer {
  class Inner {
    int iv = 100;
  }
  void outerMethod() {
    class LocalInner {
      int localInnerVar = 300;
    }
  }
    static class InnerStatic {
    int isv = 200;
  }
}

 


trycatch 문

 

package p05_Inherit;

public class Ex13trycatch {
  public static void main(String[] args) {
    System.out.println(1);
    System.out.println(2);
    System.out.println(3);
    System.out.println(10/0);
    System.out.println(5);
    System.out.println(6);
    System.out.println(7);
    System.out.println(8);
  }
}

다음 코드를 실행하면 예외 처리가 발생함

예외 처리 할 블럭을 선택하고 

[ Ctrl+alt + T ]를 사용해서 블럭을 만들어줄 수있다

 

에러가 발생하더라도 다음 코드로 진행한다

try 안에있는  System.out.println(4); 은 출력하지 않고 다음코드로 진행됨

finally는 예외가 발생해도 출력됨

 


package p05_Inherit;

public class Ex13throws {
  public static void main(String[] args) {
    method1();
    System.out.println("main");
  }

  private static void method1() {
    method2();
    System.out.println("method1");
  }

  private static void method2() {
    method3();
    System.out.println("method2");
  }

  private static void method3() {
    try {
      throw new Exception();
    } catch (Exception e) {
      //throw new RuntimeException(e);
      System.out.println("method3");
    }
  }
}

 

throws 는 책임을 회피하는  

private static void method3() throws Exception{
  try {
    throw new Exception();
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

 

모든 메소드에 throws 처리를 하면 JVM에서 에러를 내보낸다


method 재정의 할 때 접근 제어자의 범위는 같거나 넓어야한다

범위 : private <default < protected < public 

Child2.default가 Parent2.protected 보다 범위가 작기 떄문에 에러가 발생

 class Parent2 {
    protected void methode() throws ArithmeticException, IOException {
    }
  }

  class Child2 extends Parent2 {
    @Override
    protected void methode() throws ArithmeticException, IOException {
      super.methode();
    }
  }

throws는 같거나 많아야 한다

  class Parent2 {
    protected void methode() throws ArithmeticException, IOException {
    }
  }
  class Child2 extends Parent2 {
    protected void methode() throws ArithmeticException, IOException {
    }
  }

예외 처리를 만들어서 메세지 보내는 방법

public class Ex15MyException {
  public static void main(String[] args) {
    try {
      throw new MyException("내가 발생 시킨 에외");
    } catch (MyException e) {
      //throw new RuntimeException(e);
      System.out.println(e.getMessage());
    }
  }
}
class MyException extends Exception{
  public MyException(String message) {
    super(message);
  }
}

Exception 을 상속 받았기 때문에 throw 사용한다


ctrl+shift+f

프로젝트 안에있는 코드를 찾을 수 있음


 

728x90
반응형

'PROGRAMING📚 > Java📑' 카테고리의 다른 글

Java:: 입출력 Stream I/O  (0) 2024.06.27
Java :: 활용 -String  (0) 2024.06.25
Java::구성 - 배열[Array]  (0) 2024.06.21
Java::구성- switchCase  (0) 2024.06.20
Java:: 구성- 정보은닉(incapsulation),getter/setter 사용하기  (0) 2024.06.20

댓글