20210927 복습위주의 날, 다형성과 자잘한 부분 보완

DUUUPPAAN·2021년 9월 27일
0

교육 20210915~ Java

목록 보기
8/13

·복습위주의 날

-누군가 수업이 굉장히 어렵게 느껴져서 질문도 많이 하고 어렵다는 의견을 피력했나보다. 물론, 나도 어렵다. 개인적으로 수업시간에 배우는 양 == 구글링의 양; 이 되어 버려서, 정말 어렵다. 그래도 계속 복습하기 보다는, 한번 복습해주신 부분은 알아서 복습하게 하고, 더 진도를 나갔으면 한다. 다양한 것들을 해봐야 더 잘 이해될 것 같은데, 아는 내용을 계속 진행하니 집중력이 조금 떨어졌다.

·새로 배운 것. 오버라이딩

-오버로딩이라는 개념과 조금 헷갈릴 수 있다고 하셨는데, 조금 집중해서 생각해보면 크게 어렵지 않았다.
오버로딩은 동일한 이름의 메소드를 파라미터만 다르게 줘서 여러개 정의할 수 있는 기능인데, 로딩하는 인자 값이 다르게 하는 것이니까 오버로딩이라고 기억했다.

-반면에 오버라이딩은 저번에 배운 상속과 관련된 것인데, 상속을 받을 때, 상속 받은 메소드를 재정의해서 사용하는 기능이다.
여기서 주의할 점은, 재정의는 완전히 다르게 정의하진 못하고, 동일한 메소드명(재정의하는건데 이름이 다르면 그냥 다른 메소드 만드는 것이니까?) 동일한 리턴 타입, 동일한 파라미터 변수여야 한다. 단, private 메소드와 static 으로 정의된 메소드는 상속 자체가 성립이 안되기 때문에 오버라이딩도 불가하다.
사실 재정의하는 기능을 자주 쓸까에 대한 의문점은 있다. 그냥 새로 메소드를 만들면 더 편한 것 아닌가 싶기 때문에, 굳이 오버라이딩의 조건들을 지키면서 재정의할 일이 있을까 싶긴 했다.

그래도 중요한 부분이라고 하셨으니 집중해서 사용해봤다.

package Prac927;

class Person{
	String name;
	int age;
	
	public void show() {
		System.out.println("이름은 "+name+"이고, 나이는 "+age+"입니다.");
	}
}

class Student extends Person{
	String studentID;
	
	public void show() {
		System.out.println("이름은 "+name+"이고, 나이는 "+age+"입니다. 학생번호는 "+studentID+"입니다.");
	}
}

public class HeritageOverriding {

	public static void main(String[] args) {
	
	
	
	Student st = new Student();
	st.name="박수영";
	st.age=23;
	st.studentID="12192987";
	st.show();
		
	}

}

보통 이렇게 부모와 자식 클래스를 한 코드 안에 넣진 않겠지만, 간단하니 이렇게 해봤다.
이름은 박수영이고, 나이는 23입니다. 학생번호는 12192987입니다.
결과는 위와 같다. 분명 같은 메소드인 show();가 부모 클래스에 있었고, 거기에는 학생번호를 출력하라는 내용이 없었다. 그러나 자식 클래스에 와서 동일한 이름의 메소드를 재정의했고, 결과는 달라졌다. 만약 여기서 부모클래스의 객체를 만들어서 show();를 한다면?
예를 들어, 이렇게 넣는다.

Person ps = new Person();
ps.show();

결과는

이름은 박수영이고, 나이는 23입니다. 학생번호는 12192987입니다.
이름은 null이고, 나이는 0입니다.

이렇게 된다. 일단 재정의한 자식 클래스의 show();를 통해 내용이 출력되고, 부모 클래스의 객체에 있는 변수들은 스태틱 변수가 아니니 객체 생성시 초기화되어 전혀 다른 변수가 된다. 그래서 ps.show();의 결과는 아무것도 들어있지 않은 초기화 값이 된다.

·다형성

-다형성은 아직 제대로 배우진 않았고, 코드를 작성해보기만 했다. 그래서 아직 정확하게 다형성이 무엇인지는 모르겠다. 찾아보니 엄청나게 복잡한 설명들이 있었다. 그러나 간단하게 생각하자면, 큰 객체 안에 작은 객체를 넣어서 여러 부분에서 사용하는 것이다. 위의 작성한 코드를 조금 변형해봤다.

package Prac927;

class Person2{
	String name;
	int age;
	String studentID;
	
	public void show() {
		System.out.println("이름은 "+name+"이고, 나이는 "+age+"입니다.");
	}
}

class Student2 extends Person2{
	
	
	public void show() {
		System.out.println("이름은 "+name+"이고, 나이는 "+age+"입니다. 학생번호는 "+studentID+"입니다.");
	}
	public void naming() {
		System.out.println("넌 박수영이야!");
	}
}

public class Dahyungseong {

	public static void main(String[] args) {
	
	
	
	Person2 ps = new Student2();
	ps.name="박수영";
	ps.age=23;
	ps.studentID="12192987";
	ps.show();
	
	// ps.naming();
	}

}

위와 비슷하지만, 우선 변수들을 자식 객체에서 추가적으로 선언하지는 않았다. 다만 메소드를 부모쪽 메소드를 재정의 한 것과, 자식 클래스 본인만 가지고 있는 메소드 두 개를 작성했다.
보통 우리는 객체를 생성할 때, 해당 객체의 클래스 이름에 해당하는 클래스의 이름으로된 메소드를 넣어줬다. 예를 들면

Person ps = new Person();
Student st = new Student();

이런 식으로.
그런데 다형성 중에 UpCasting이라는 것을 활용하면, 큰 개념의 객체인 Person ps 안에 작은 개념의 객체인 Student()를 넣어서 활용할 수 있다.
Person ps = new Student();
반대의 경우는 DownCasting이라고 하는데 아직 제대로 배우지는 못했다. 기본적으로는 허용하지 않는다고만 하셨다.
그냥 단순하게 생각해보면 작은 개념에 큰 개념을 넣는 것이 이상하기 때문이라고 이해했다.

자 그럼 위의 변경된 예에서 보면,
ps.show();는 Person의 메소드 show();인지 Student의 메소드 show();인지 헷갈릴 것이다.
결론은

이름은 박수영이고, 나이는 23입니다. 학생번호는 12192987입니다.

Student의 show();가 사용되었다. 분명 Person클래스의 객체인데, 내용을 Student로 넣어줘서 저런 결과가 나왔다. 그러면, ps.naming();의 결과는?
컴파일 오류가 난다.
왜냐하면, 부모클래스에서 show();라는 동일 이름의 메소드가 있지만, naming이라는 메소드는 없기 때문에 참조가 불가능하다. 사실 이 부분도 확실하게 이해했는지는 잘 모르겠다. 우선은 이정도로만 이해하고 넘어가려고 한다. 내일 더 깊게 들어가실테니 내일 잘 이해해보도록 하자.

·점점 어려워지는 코드

-다형성? 점점 그게 왜 존재해야하는지에 대한 의문이 든다. 그런데 분명 필요하다고 하셨으니 그 용도가 엄청나게 많거나 분명하게 알고 있어야 하는 느낌이 든다. 큰 산이 앞에 있는 느낌이다. 내일은 꼭 학원으로 가서 확실하게 집중해야겠다.

profile
비전공자란 이름으로 새로운 길을 가려 하는 신입

0개의 댓글