국비교육(22-23)

17일차(1)/java(16) : 상속, 다형성, 접근지정자 정리

서리/Seori 2022. 10. 28. 15:32

17일차(1)/java(16) : 상속, 다형성, 접근지정자 정리

(16일차 수업 요약)

 

 

[ 상속 / extend ]

 

상속한 부모클래스의 기능을 사용할 수 있게 되는것

- extends를 따로 적지 않으면 자동으로 object를 상속받게 되어 있다.

- (Object, Phone, HandPhone 클래스를 상속한) SmartPhone 생성자를 호출하면
heap영역에 4가지 기능을 모두 가지고 있는 객체가 만들어진다. 상속되어 있기 때문에!

- 반대로 HandPhone의 생성자를 호출해서 SmartPhone이 기능을 사용할 수는 없다.

 자식 객체쪽이 더 좁은 개념인 것!



[ 다형성 ]

 

- 다양한 타입을 띠고 있다는 뜻.

- new SmartPhone; 해서 참조값을 변수나 필드에 담을때 타입을 설정해야 하는데, 

 SmartPhone의 경우 타입을 4가지 공간에 담을 수 있다. 
→ 스마트폰 객체는 4가지 타입을 가지고 있다!
   자식 객체를 부모 타입으로 받을 수 있기 때문에.

- 사실 SmartPhone 객체는 그냥 SmartPhone 타입으로 받아도 되는거지만,

  프로그래밍의 유연성을 위해 부모타입으로 받아야할 때가 있다.
- 타입이라는 것은 그 공간에 대한 사용설명서 역할 : Object로 정의되면 Object의 기능밖에 쓰지 못한다.

★필드나 지역변수의 타입은 그 안에 들어있는 값에 대한 사용설명서, 사용 지침의 역할을 한다.

- 아무리 SmartPhone 객체를 생성했다 해도 사용설명서가 다른 타입이면 그 기능을 다 쓸 수 없다.
- heap영역에 가보면 실제로 HandPhone객체가 들어있지만, 설명서가 부모타입이면 그 부모타입에 맞는 기능만 사용할 수 있다고 생각하면 된다.

 




- 어떤 타입의 변수를 만드는 것과 객체를 만드는 것은 다르다.
HandPhone p1=null; 

: 지역변수가 만들어진 것! 참조값을 담을 수 있는 p1이라는 이름의 공간일뿐, 객체가 아니다.

 

public static void main(String[] args) {
	HandPhone p1=new HandPhone();
	Phone p2=p1;
	Object p3=p1;
}

- MainClass03 을 보면 지역변수는 3개, 객체는 1개 만들어진 것이다.
 객체를 하나 생성해서(new) 참조값을 p1, p2, p3이라는 지역변수에 다 넣어준 것.
 동일한 키값이 p1, p2, p3에 다 들어가 있다.

- 동일한 객체임에도 불구하고, 어떤 타입의 공간에 들어가 있느냐에 따라서 사용할 수 있는 범위가 달라진다!

 

- 캐스팅(casting) 중요!!★

- 자바의 모든 객체는 올라가보면 object 타입. object가 가장 넓은 범위에 있다!

- 캐스팅 연산자를 바라보는 관점

: 실제 변수는 object타입이지만 캐스팅 연산자는 그 위치에 있는 타입을 강제로 바꾸어 인식시키는 것이다.

 


 

[ 접근 지정자 ]

- private : 비공개(나에게만). 나=객체 안쪽, 또는 클래스 안쪽

 

- default : 접근지정자를 아예 생략하면(지우면) 같은 패키지 내에서만 사용 가능

 굳이 표기하지 않고,  동일한 패키지에서 생성한 클래스 또는 객체에서만 접근할 수 있음

 

- protected는 상속관계에서만(default를 확장한 개념)

 

- private<default<protected<public 순으로 범위가 넓어진다!

 

- 클래스는 접근지정자를 2가지 종류밖에 사용하지 못하는데(default와 public) import 가능 여부를 결정하기 때문!

 같은 패키지에서만 import되는가, 패키지가 달라도 import가 되는가 만 구분하면 되어서.

 (상속관계 등과는 무관하고, 내 클래스 안에서 import는 할 필요가 없으므로!)

 


- 클래스와 객체를 혼돈하는 경향이 있는데
 객체는 new 하면 생성되는 것이고, 클래스는 객체의 설계도이다.
(but static field/method를 가지고있는 클래스는 설계도가 아니다. 객체와 관계가 없고, new없이 클래스 자체로 사용)

 

1) static 자원에 private를 붙이면
- private는 클래스 내부에서만 사용가능. 클래스 내부의 다른 메소드에서는 쓸수있지만 클래스 외부에서는안된다.
(static이어도)

 

 

2) 일반 자원에 private를 붙이면
- static이 아니므로 바로 점 찍어서 호출할 수 없고, → MyObject.send(); X
  new 해서 호출해서 사용해야 한다.   new MyObject().send(); O

- private는 객체 내부에서 사용할 수 있다.

 


 

- 생성자를 정의하지 않아도 디폴트 생성자는 있다.

- 생성자를 하나라도 정의하면 디폴트 생성자는 사라진다.

 

- new 해서 생성되는 객체는 car 객체의 engine 이라는 이름의 필드에 저장되는 것이다.

 

- 객체를 처음 만들 때 필요한 값을 생성자를 통해서 전달한다.

 생성하면서 값을 넣어준다! 전달된 값을 필드에 저장하는 것.

 

- 필드에 보관했다가 나중에 메소드가 호출되었을 때 사용하기위해서

 

ex) 리모콘 객체라고하면, 필드는 건전지, 채널/볼륨 등 기능을 작동시키는 버튼이 메소드

 

- 메소드가 정상적으로 동작하기 위한 부품이나 데이터가 필드에 들어있다.

 

 

- Car객체의 engine 필드가 있어야만 car 안의 drive 메소드를 사용할 수 있다.

 위와 같이 저장할 필드가 없으면, 생성자의 매개변수에서 받은 데이터를 저장해둘 수 없다.

 

- 메소드의 지역변수들은 메소드가 수행될 때만 잠깐 나타나고 메소드가 끝나면 사라지기 때문에

 어떤 값을 넣어둔 상태로 유지하려면 필드에 저장해야 한다.

- 필드는 javascript의 global variable(전역변수)역할과 비슷하다고 할 수 있다.

 


- Scanner객체 생성은? new Scanner(System.in)

 과연 이 중에 어떤 생성자를 호출한 것인가??

 

- System.in 은 inputStream 타입이다.(키보드와 연결된 특별한 객체) → 2번 생성자를 사용한 것.

 (네트워크와 연결될수도 있고, 파일시스템 내의 텍스트파일과 연결될 수도 있다)

 InputStream은 어떻게만드냐에 따라서 다 다르다. 읽어오는 곳에 따라다른것)

 

- 콘솔 출력도 System.out 이 콘솔과 연결되도록 자바에서 만들어둔 것.

 

- java 프로그램 내에 이렇게 정의되어 있다고 할 수 있다.

 System 클래스에 InputStream 타입의 in이라는 static 필드가 있는 것.

 

- System.in.read() 라고 읽어내는 기능도 있는데 int값이고, 키 코드값만 읽어낸다.

 Scanner객체의 메소드는 상대적으로 편하게 읽어내는 기능이다.ㅎㅎ

 

package test.auto;

public class ElectricCar extends Car {
	
	//부모객체가 생성되기 위해서 필요한 객체를 자식 생성자의 매개변수로 전달받아서
	public ElectricCar(Engine engine) {
		//부모 생성자에 전달을 해주어야 한다.
		super(engine);		
	}	
	public void charge() {
		System.out.println("충전을 해요!");
	}
}

 

- 어떤 클래스를 상속받은 후 생성하면 부모 객체도 같이 만들어지는데,

 부모객체를 만드는과정에서 필요한 값이 있으면 객체가 만들어지지 않고 오류가 발생한다.

 

- 부모객체가 디폴트 생성자도 가지고 있으면 ElectricCar를 생성할 때 다른 생성자를 넣어주지 않아도 오류가 나지 않는데,

 지금 Car에는 디폴트 생성자 public Car(){ } 가 없다.

- 그래서 현재 있는 Car의 생성자를 가지고 호출해야하는데, 이 Car의 생성자에는 매개변수 engine이 필요하다.

그래서 super(engine); 이라는 객체를 만들어 매개변수로 전달하는 과정이 필요한 것이다!

 

 

- 보통 클래스를 마음대로 만들기는 힘들다.
 대부분은 어떤 인터페이스를 구현해서 만들거나, 무언가를 상속받아서 만드는 경우가 많다.

 

- 클래스를 만들 때 강제로 상속받는 클래스에서 override하도록 만들어둘 수도 있다.
  메소드를 미완성인 상태로 만들어두어서 상속해간 이후에 수정하도록 하는 것.
- 왜 완성해두지 않는가? 사용할 개발자가 어떤 용도로 사용할지 모르기 때문에,

 기반만 만들어놓고 메소드는 수정할 수 있도록 만들어두는 것.

 → 다음 게시물 abstract class에서 더 자세히!