생각기록

2023-03-04 java / 클래스의 상속 / 오버라이딩 본문

SeSAC 풀스택/JAVA &Spring boot

2023-03-04 java / 클래스의 상속 / 오버라이딩

끼록관 2023. 3. 4. 13:11

전시간

더보기

 

클래스의 구조

필드

 

생성자 ( js와 비슷 이름이 같다)

 

메소드 (메소드 앞 자료형은 이 함수가 결국 반환할 값)

 

 

메소드 형태

리턴값이 없으면, void

 

생성자도 결국 메소드 중 하나

 

Class 사용 ( = 객체 만든다 ) 

자바에서는 메인메소드가 제일 먼저 실행이 됩니다.

그 안에서 객체를 만들어서

 

.new 키워드 사용

위의 사진의 public ClassName() 생성자를 의함

자료형 변수명 = new 자료(); 

 

 

접근 제어자

public 모든곳에서 접근 가능

protected 동일 패키지 or 자식 클래스에 허용

default 동일 패키지에 허용

private 외부로부터 완벽차단

 

getter & setter

문법적으로 정해진 것은 아님

필드. 변수를 private로 지정하는게 일반적이여서 필요함 ( 보안적, 외부 접근 막음 )

 

접근을 못하게 했는데

이 변수를 가져온다던가 다시 지정한다는지.. 이런 기능이 필요해서 있는 메소드가 getter와 setter입니다.

 

get은 가져온다 > return 

set 값을 설정 > 안에 바꿔주는 코드가 있어야함

 


보통 객체는

뭐라고 찍힐까요?

3

객체 마다 필드의 공간, 메모리가 다르다.

test.number = 2

test1.number = 3

test.number = 4

 

test.number는 4가 되고, test1.number 는 3이 된다.

각자 다른 공간을 가지게 된다.

 

하지만 static 멤버는!!!

 

static 멤버 ( 변수, 메소드 )

1. 객체마다 생성되는 것이 아니고, 클래스 당 하나만 생성 됨 => 클래스의 틀을 이용해서 찍어내는게 객체임

2. 클래스가 생성되는 순간 메모리를 할당 받음 ( 클래스는 일종의 틀 )

3. 즉, 객체를 생성하지 않아도 static 멤버의 접근 가능  ( 일반 객체는 객체를 생성하고 타고 들어가야하는데!!

***객체 생성 없이 클레스 네임 타고 갈 수 있다. ClassName.name 가능 )

4. 동일한 클래스의 모든 인스턴스에 공유됨. (모든 객체가 하나의 공간을 공유 = 같은 메모리 공간 공유)

5. non-static의 경우 객체가 생성될 때마다 멤버 공간을 새로 만듬 ㅡ> 메모리 공간 공유 x 

둘다 "성춘향" 이 찍힘

클래스로 만든 name이라는 공간은 같은 주소를 가르키고 있기 때문!

 

static의 활용

보통 static 변수는 공유의 목적으로 많이 사용

펄슨 클래스를 만들어서 명수를 세고 싶음 ( 객체의 갯수 ) 그 때 static으로 하면?

클래스 몇개의 인스턴스가 있는지?

public static int COUNT = 0;

 

static 맴버 (변수, 메소드) 인

count를 public으로 만들어서 

객체 생성 없이

해도 찍히더라... 

 

 

 

 

 

클래스의 상속

부모 클래스에서 정의된 필드(멤버)와 메소드를 자식 클래스가 물려받는 것

 

장점

멤버의 중복 장성 제거

클래스의 계층적 분류 가능

클래스의 재사용과 확장성 용이

 

 

중복되는 것은 부모에게 물려받고, 특징만 쓰면 된다.

 

클래스 상속 예시

아래와 같이 신분 별로 클래스를 정의했다고 했을 때,

"말하기, 먹기, 걷기, 잠자기"의 행동은 모든 신분에서 동일하게 정의

학생, 알바+학생, 연구자, 교수

 

  • 이를 계층화 해서 아래와 같이 표현 가능
  • Person이라는 부모 클래스를 만들고 Student, Researcher, ... 클래스에서 상속받도록 하는 것!

중요한 것은 공통적인것을 묶을 줄 알아야 함!!

StudentWorker 같은 경우 Studernt만 상속해도 person 까지 상속된다!

 

Person 과의 관계에서 Studernt를 자식 클래스, 혹은 서브 클래스 

Person 은 부모, 슈퍼클래스라고 한다.

 

 

상속 문법

extends 를 쓰면, 뒤에있는 것을 상속받겠다라는 뜻

 

... 안에 정의된 내용 => name이라는 필드가 person 에 있으면, researcher 클레스에 지정하지 않아도 자동으로 name이란 필드를 갖게 됩니다.

 

 

package java_first_project;

public class Person {
	// 사람이라면, 가지는 속성
	protected String name;
	private int age;
	
	
	public void test() {
		System.out.println("test");
	}
	
	// 메소드 오버로딩 
	// 생성자도 여러개 가능
	// 생성자 둘 중 누굴 실행할지는 메인에서 매개변수 타입, 갯수에 따라 실행이 다름!
	
	// 얘는 왜 실행되는가? >> Student() 생성자에서 실행됨
	// 만약에 생성자를 적지않으면, 그냥 아무것도 하지 않는 생성자가 자동으로 생성됨  public Person(){} / 다른것을 만들었으면 저런 형태의 생성자가 없다.
	public Person() {
		System.out.println("사람 클래스의 인스턴스 생성됨");
	}

	public Person(String name, int age) {
		System.out.println("사람 클래스의 인스턴스 생성됨2");
		// private String name = this.name
		this.name = name;
		this.age = age;
	}
	
	
	// getter & setter
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	// 메소드도 같은 이름으로 여러개를 만들어 줄 수 있다.
	// 메소드 오버로딩이라고 검색 > 같은이름으로 여러개의 함수를 만드는 것
	// 사람이라면, 하는 일
	public void sleep() {
		System.out.println("쿨쿨 잠을 잔다.");
	}
	// 같은 이름으로 다른일을 해야함 단, 매개변수가 달라야 한다.
	public void sleep(int n) {
		System.out.println("쿨쿨 잠을 잔다.");
	}
}
package java_first_project;

//extends Person => Person을 상속받음 (name, age, 자는 행동)
// 학생이하는 특징적인 일들만 적어주면 된다.
public class Student extends Person{
	
	private String studentID;
	
	// 자식에서 하는 메소드 오버라이딩 > 내용은 달라도 되지만! 단, 함수의 원형이 같아야 한다.
	public void test() {
		System.out.println("student test");
	}
	
	public void sleep() {
		System.out.println("쿨쿨 학생은 11시에 잠을 잔다.");
	}
	
	// 생성자
	// 생성자 선택 > super(); 직접 선택 가능
	public Student () {
		// person을 상속받고 있어서 Student 생성자 제일 윗줄에서 실행한다.
		//Person(); 기본생성자가(아무것도 받지 않는 생성자)아닌 매개변수를 받는 생성자를 실행시키고 싶다면?
		// super 부모 클래스의 생성자를 실행 시키겠다. 아무것도 없으면, 기본실행자 
//		super("홍길동", 99);
		
		// protected 라접근 가능 ( 동일, 부모자식 중 하나면 접근 가능 )
		this.name = "성추냥";
		// private 로 되어있어 Person 클래스내에서만 접근 가능 ( 상속과 상관없는 관계를 생각할 필요가 없는 아이)
//		this.age = 99;
		System.out.println("Student 생성자 실행됨");
	}
	
	// getter * setter
	public String getStudentID() {
		return studentID;
	}

	public void setStudentID(String studentID) {
		this.studentID = studentID;
	}
	
	
	
	
	//메소드
	public void study() {
		System.out.println("공부 하기");
	}


}
package java_first_project;

public class Main {
	
	
	public static void main(String[] args) {
		
		// 사람 특성을 가진 객체가 생성
		Person p = new Person("홍길동", 55);
		p.sleep();
		
		// 사람 특징과 학생특징을 가지고 있는 객체
		Student s = new Student();
		s.sleep();
		
		// 이순간에는 홍길동이 나옴
		System.out.println(s.getName());
		
		// Student에 setName이 없어도 상속받은 메소드를 사용이 가능
		// 하지만, 이순간에는 성춘향이 나옵니다. 
		s.setName("성춘향");
		System.out.println(s.getName());		
	}
}

상속받은 클래스의 생성자 먼저 실행하고, 자기가 하려던일을 한다.

 

2가 두번인 이유

super(); 은 부모 클래스의 기본 생성자를 선택

super(인자 ... ); 부모 클래스의 인자가 있는 생성자를 선택

 

 

 

 

 

 

 

부모 클래스 TestClass

접근제어자 protected / defualt 의 차이점

예시1 / 부모 필드가 protected인 값은 자식이 접근이 가능하다.
예시2

다른 패키지의 클래스를 상속하고 싶다면,

import로 외부의 것을 가져온다. => 패키지 이름.파일이름

protected는 패키지가 달라도 상속받은 자식이면, 접근이 가능하다.

 

상속과 관련됬다면

protected 도 가능하지만, 멤버 이름이 같아서 생기는 사항도 있으니

보통 private를 쓴다.

 

 

상속 간단 예제

public, protected면 접근이 가능

 

첫줄에서 써야한다 super( );  안에있는 내용을 실행시키기 전에 해야해서 ㅇㅇ..

 

 

메소드 오버라이딩

* 메소드 오버로딩(함수 오버로딩)  ㅡ> 여러개의 메소드(함수)가 같은 이름을 가질 수 있다. 단, 매개변수가 달라야한다.

  • 오버라이딩은 상속과 관련된 개념 (class 와 상속과 관련됨)
  • 메소드의이름, 매개변수타입개수, 리턴타입모든것을동일하게작성.
  • 부모클래스에 정의한 메소드를, 자식클래스에서 다시 정의하는 것을 메소드 오버라이딩이라고 한다.

부모 클래스

자식 클래스

 

또다른 예시

부모 클래스

 

자식 클래스

p는 부모

s는 자식

 

오버라이딩


상속 실습

animal

package java_first_project;

public class Animal {
	// 종, 이름, 나이 변수
	private String type;
	private String name;
	private int age;
	
	
	// 메소드
	public void makeSound() {
		System.out.println("동물은 소리를 낸다.");
	}

	// getter & setter
	public String getType() {
		return type;
	}


	public void setType(String type) {
		this.type = type;
	}


	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public int getAge() {
		return age;
	}


	public void setAge(int age) {
		this.age = age;
	}
}



cat

package java_first_project;

public class Cat extends Animal {
	
	// 생성자
	public Cat(String type, String name, int age) {
		this.setType(type);
		this.setName(name);
		this.setAge(age);
	}
	
	// 메소드
	public void makeSound() {
		System.out.println("고양이는 냐오오옹캬오옹 운다.");
	}
}


dog

package java_first_project;

public class Dog extends Animal{
	
	// 생성자
	public Dog(String type, String name, int age) {
		this.setType(type);
		this.setName(name);
		this.setAge(age);
	}
	
	// 메소드 오버라이드
	public void makeSound() {
		System.out.println("강이지는 왈앙아르르르르르 운다.");
	}
}

main
package java_first_project;

public class Main {
	
	public static void main(String[] args) {
		
		Dog dog = new Dog("잉글랜드 포인터","완이", 3);
		System.out.println("종은 " + dog.getType()+ " 이름은 " + dog.getName() + " 나이는 " + dog.getAge() + "살 입니다.");
		dog.makeSound();
		
		Cat cat = new Cat("스코티쉬 스트레이트","수남", 10);
		System.out.println("종은 " + cat.getType()+ " 이름은 " + cat.getName() + " 나이는 " + cat.getAge() + "살 입니다.");
		cat.makeSound();
		
	}
}

// 부모 Car
package java_first_project;

public class Car {
	// 차의 공통점 크기 / 속도 / 인승 
	private String type;
	private int speed;
	private int people;
	
	// 생성자
	public Car(String type, int speed, int people) {
		this.setType(type);
		this.setSpeed(speed);
		this.setPeople(people);
	}
	
	// 메소드
	public void running() {
		System.out.println("슈우우우우우우우웅 달림");
	}

	// getter & setter
	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public int getSpeed() {
		return speed;
	}

	public void setSpeed(int speed) {
		this.speed = speed;
	}

	public int getPeople() {
		return people;
	}

	public void setPeople(int people) {
		this.people = people;
	}		
	
}


//자식 Bus
package java_first_project;

public class Bus extends Car{
	// 요금
	private int fee;
	
	public Bus(int fee) {
		super("대형", 50, 20);
		this.fee = fee;
	}
	

	// 메소드
	public void running() {
		System.out.println("삐삑 요금이 처리되었습니다.");
	}
	
	
	public int getFee() {
		return fee;
	}

	public void setFee(int fee) {
		this.fee = fee;
	}
}


// 자식 Motorcycle
package java_first_project;

public class Motorcycle extends Car {
	
	private String delivery;
	
	public Motorcycle(String delivery) {
		super("소형", 100, 2);
		this.delivery = delivery;
	}
	

	// 메소드
	public void running() {
		System.out.println("부르르르르르릉 오토바이");
	}
	
	
	
	public String getDelivery() {
		return delivery;
	}

	public void setDelivery(String delivery) {
		this.delivery = delivery;
	}
}


 // main
 package java_first_project;

public class Main {
	
	public static void main(String[] args) {

		Bus bus = new Bus(1500);
		System.out.println("버스의 타입은:" + bus.getType() + " 속도는:" + bus.getSpeed() + " 몇인승:" + bus.getPeople() + " 요금은:" + bus.getFee() + "원 입니다.");
		bus.running();
		
		
		Motorcycle motorcycle = new Motorcycle("배달 가는 중");
		System.out.println("모터사이클의 타입은:" + motorcycle.getType() + " 속도는:" + motorcycle.getSpeed() + " 몇인승:" + motorcycle.getPeople() + " 지금 뭐하나:" + motorcycle.getDelivery() + " 입니다.");
		motorcycle.running();
		
	}
}