[상속]super, Override, Overload, final

EUNJI LEE·2023년 4월 12일
0

JAVA

목록 보기
5/12

상속(Inherit)

상속은 다른 클래스가 가지고 있는 필드, 메소드를 현재 클래스에서 직접 만들지 않고 물려 받음으로써 자신 것처럼 사용할 수 있는 것을 말한다. 반복해서 사용하게 될 클래스의 재사용, 연관된 클래스들에 대한 공통적인 규약을 정의하기 위해서 만들어졌다. 이 덕분에 코드 작성 양이 줄어들고 공통적으로 관리하는 부분에 있어서 유지 보수에 더욱 편리해졌다.

클래스 상속은 클래스 선언부에 extends 라는 예약어를 사용해주면 된다. public class SubTest extends SuperTest{ } 형태로 선언할 수 있다. 상속을 해주는 쪽이 부모(super) 클래스이고, 받는 쪽이 자식(sub) 클래스가 된다.

💡 모든 클래스는 Object 클래스를 상속 받는다. Object 클래스는 최상위 부모 클래스라고 볼 수 있다. 여태 사용해왔던 toString(), equals() 같은 메소드들은 전부 Object라는 클래스에서 상속 받아 쓸 수 있었던 기능들이다.

  • 상속 클래스 선언 예시
    학원의 인원 관리 시스템을 만들고자 할 때 학생과 강사 클래스를 나눠서 전부 선언하는 것이 아니고 공통된 부분은 Person 클래스에서 만들고 Student, Teacher 클래스가 각 메소드들을 상속받아서 사용할 수 있도록 한다. 이러면 추가로 강사가 아닌 직원을 관리하는 클래스를 만드려고 해도 기본 정보는 Person 클래스에서 상속 받아 사용하고 필요한 부분만 추가적으로 작성해서 관리할 수 있다.
    public class Person {
    	private String name;
    	private int age;
    	private char gender;
    	private String phone;
    	private String address;
    	
    	public Person() {}
    
    	public Person(String name, int age, char gender, String phone, String address) {
    		super();
    		this.name = name;
    		this.age = age;
    		this.gender = gender;
    		this.phone = phone;
    		this.address = address;
    
    //setter, getter 생략
    	}
    public class Teacher extends Person{
    	//이름, 나이, 성별, 전화번호, 주소
    	//과목, 경력, 연봉
    	private String subject;
    	private int career;
    	private int salary;
    	
    	public Teacher() {}
    
    	public Teacher(String name, int age, char gender, String phone,
             String address,String subject, int career, int salary) {
    		super(name,age,gender,phone,address);
    		this.subject = subject;
    		this.career = career;
    		this.salary = salary;
    
    //setter, getter 생략
    	}
    public class Student extends Person{
    	//이름, 나이, 성별, 전화번호, 주소
    	//수강과목, 특이사항, 수준
    	private String joinClass;
    	private String issue;
    	private char level;
    
    	public Student(String name, int age, char gender, String phone,
               String address,String joinClass, String issue, char level) {
    		super(name,age,gender,phone,address);
    		this.joinClass = joinClass;
    		this.issue = issue;
    		this.level = level;
    
    //setter, getter 생략
    	}

💡 상속 받은 클래스 간에도 private으로 선언한 멤버는 직접 접근은 불가하다. 상속 자체는 되지만 접근 제한자의 영향을 받는다는 것이다. 이때도 마찬가지로 setter, getter 메소드를 이용해서 접근하거나 super() 메소드를 이용하여 전달 받은 부모 필드에 값을 부모 생성자 쪽으로 넘겨서 생성해야 한다.

💡JAVA는 단일 상속만 지원

단일 상속은 자식 클래스가 부모 클래스를 하나만 갖는 것을 의미한다. 클래스 간의 다중 상속보다 명확하고 신뢰성 있는 코드를 작성할 수 있다는 특징을 가진다.

C++에서는 다중 상속 기능을 제공하는데 이는 서로 다른 부모 클래스로부터 상속 받은 필드 간의 이름이 같은 경우 문제가 발생할 수 있다. 어느 부모 클래스의 필드인지 찾아내야하기 때문이다. 하지만, 여러 클래스에서 상속 받으면서 복합적인 기능을 가진 클래스를 보다 쉽게 작성할 수 있다는 장점도 있다.

super()와 super.

super()부모 생성자를 호출하는 메소드이다. 기본적으로 자식 생성자에 부모 생성자가 포함되어 있는데 자식 객체 생성 시에는 부모부터 생성이 되기 때문에 자식 클래스 생성자 안에서는 부모 생성자를 호출하는 super() 이 첫 줄에 존재한다. 부모 생성자가 먼저 실행되기 때문에 명시적으로 작성할 때도 반드시 첫 줄에만 작성해야 한다. 매개변수가 있는 경우에는 super(매개변수) 로 작성할 수 있다.

//Student 클래스라는 자식 클래스에서 Person 클래스라는 부모 클래스에서 생성자를 호출
//Person 클래스의 Person(매개변수) 생성자
public Person(String name, int age, char gender, String phone, String address) {
		super();
		this.name = name;
		this.age = age;
		this.gender = gender;
		this.phone = phone;
		this.address = address;
	}

//Student 클래스의 Student(매개변수) 생성자
public Student(String name, int age, char gender, String phone, String address,
          String joinClass, String issue, char level) {
		super(name,age,gender,phone,address);
		this.joinClass = joinClass;
		this.issue = issue;
		this.level = level;
	}

💡 자식 클래스에서 매개변수 생성자를 호출할 때 super()를 사용했어도 받을 매개변수는 전부 입력해주어야 한다.
부모 클래스에 매개변수 생성자를 사용했을 때는 반드시 기본 생성자도 함께 선언
해줘야 한다. 부모 클래스에 매개변수 생성자만 선언하고 나면 자식 클래스에 매개변수 선언자밖에 사용 못한다.

super.는 상속을 통해 자식 클래스를 정의할 때 해당 자식 클래스의 부모 객체를 가리키는 참조 변수이다. 자식 클래스 내부에서 부모 클래스 객체에 접근하여 필드, 메소드를 호출할 때 사용한다.

//Student 클래스라는 자식 클래스에서 Person 클래스라는 부모 클래스에서 메소드 호출
//Person 클래스의 infoPerson 메소드
protected String infoPerson() { //Cotroller에서 뜨지 않도록 막을 수 있다.
		return this.name+" "+this.age+" "+this.gender+" "+this.phone+" "+this.address;
	}

//Student 클래스의 infoStudent 메소드
public String infoStudent() {
		return super.infoPerson()+" "+this.joinClass+" "+this.issue+" "+this.level;
	}

오버라이딩(Overriding)

자식 클래스가 상속 받은 부모 메소드를 재작성 해서 사용하는 것을 말한다. 부모가 제공하는 기능을 자식 클래스가 일부분을 고쳐서 사용하겠다는 의미로 자식 객체를 통해 실행시켰을 때 자식이 우선권을 가져간다.

override메소드 선언부를 부모에 선언된 메소드와 동일하게 선언해야 한다. 메소드 명,매개변수가 달라지면 오버라이드가 아닌 자식 클래스에 생성된 새로운 메소드로 구분하기 때문이다. { }안, 구현부만 달라야 오버라이드 된다.

메소드 헤드라인 위에 반드시 Annotation을 표시해주어야 한다. @Override로 표시할 수 있다. Annotation을 선언하면 오버라이드가 맞는지 확인을 해주는 기능을 한다. 부모 클래스에 같은 메소드명이 없을 때는 오류 메시지를 띄워준다.
⚠️The method 메소드명() of type 서브클래스 must override or implement a supertype method

@Override
	public boolean equals(Object o) {
		//객체에 동등 비교를 하기 위해 equals 기능을 재정의
		//같은 객체로 구분할 수 있는 필드를 정해서 비교
		Student s=(Student)o;
		if(getName().equals(s.getName())&&getAge()==(s.getAge())
				//그냥 getName()을 쓰면 앞에서 접근한 곳에서 불러온다
				&&getPhone().equals(s.getPhone())){
     return true; //이름, 나이, 핸드폰 번호가 같으면 같은 객체로 구분.
		}
		return false;
	}
✅ Object는 최상위 부모 클래스로 Object에서 제공하는 메소드 기능도 오버라이딩 가능하다.
  • 💡Object 클래스의 메소드를 재정의 해서 사용
    equals : 객체 간의 동등 비료를 하기 위해 선언한 메소드. 위에 작성한 코드처럼 재정의 해서 사용할 수 있다.
    hashCode : 객체의 유일한 값을 정수로 출력(주소)해준다. 생성된 객체의 유일한 아이디 값으로 사용한다.
    toString : 생성된 객체의 대표하는 문자를 반환해준다.
    @Override
    public String toString() {
    		return super.infoPerson()+" "+this.subject+" "+this.career+" "+this.salary;
    	} //toString()을 사용하면 내가 작성한대로 문자열을 반환할 수 있다.
    clone : 생성된 객체를 복사해주는 기능으로 깊은 복사를 구현한다.
    @Override
    	public Student clone() {
    		return new Student(getName(),getAge(),getGender(),getAddress(),getPhone()
               ,joinClass,issue,level);
    	}
    //clone()을 사용하면 작성한 순서대로 복사해서 새로운 객체를 만들어준다.

오버로딩(Overloading)

한 클래스 내에서 같은 이름의 메소드를 여러 개 정의하는 것을 말한다. 메소드의 리턴 타입은 오버로딩 조건과는 관계가 없다.

💡오버로딩 조건

  1. 메소드 이름이 같아야 한다. 여러 메소드의 이름은 동일하되 처리하는 기능과 그에 따른 결과값은 모두 다르게 하는 것이다.
  2. 매개변수의 개수 또는 타입, 순서가 달라야 한다. 오버로딩은 여러 메소드의 이름이 동일해야 하기 때문에 입력 값에 따른 처리 기능을 구별하는 기준이 매개변수가 된다. 만약 매개변수의 자료형과 순서가 동일하면 오버로딩으로 구분할 수 없다.
  3. 리턴 타입은 오버로딩 성립에 영향을 주지 않는다. 동일한 이름을 가진 메소드들의 매개변수의 타입과 개수가 같고 리턴 타입만 다르면 오버로딩은 성립되지 않는다.

final 예약어

final 예약어는 상속이 불가능한 클래스를 만들거나 상속 시 오버라이딩이 불가능한 메소드를 만들 때 사용한다. final의 의미와 정반대 되는 abstract 예약어와는 동시에 사용할 수 없다.

profile
천천히 기록해보는 비비로그

0개의 댓글