본문 바로가기
JAVA

2022-10-14 객체지향언어 - 생성자, 상속

by HTT 2022. 10. 17.

생성자

 


-> opp.basic.constructor 패키지

 

: 생성자는 객체가 생성될 때 한 번!! 호출되는 메소드


▶  클래스타입 변수 = new 생성자메소드()
                                       ----------------------
                                              ㄴ클래스 내부

- new연산자가 생성자 메소드를 보고 메모리에 할당할 클래스가 무엇인지 파악하고 생성자메소드를 호출해야 하므로 지켜야 하는 규칙이 존재한다.

 


▶  규칙

1) 생성자를 정의하지 않으면 컴파일러가 자동으로 매개변수가 없는 생성자를 추가한다.
   => 매개변수가 없는 생성자를 기본생성자라 한다.

2) 생성자메소드는 항상 반환값이 없기 때문에 리턴타입을 명시하지 않는다.(void조차 명시하지 않음)

3) 생성자메소드명은 클래스명과 대소문자까지 동일하게 정의한다.

4) 생성자메소드에 매개변수를 추가할 수 있다.

5) 생성자메소드도 오버로딩이 가능하다.
   => 일반메소드처럼 매개변수 갯수나 타입을 다르게 해서 여러 개 정의하여 쓸 수 있다.

6) 생성자를 정의하면 컴파일러는 기본생성자를 정의하지 않는다.
   => 기본생성자는 자바 프레임워크에서 기본으로 호툴되는 경우가 많으므로 작업할 내용이 없어도 기본생성자는 항상 정의해야 한다.

7) 모드 생성자의 천 번째 문장은 super()가 생략되어 있다.

8) 생성자가 오버로딩이 되어 있으므로 생성자 안에서 자신의 생성자를 호출할 수 있다.

 

 

▶  문법


this(호출하고 싶은 생성자의 매개변수 스펙에 맞게 값을 전달)
=> 반드시 생성자를 호출하는 명령문은 생성자의 첫 번째 문장에 정의해야 한다.
=> this(.....)를 호출해서 사용하는 경우는 super(.....)를 같이 호출할 수 없다.

 

 

- 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메소드'이다.

 

- 인스턴스 변수(iv)를 초기화하기 편하게 하려고 사용한다.

 

- 기본생성자는 꼭 만들어줘야 한다.

 

- 모든 클래스는 반드시 생성자를 가져야 한다(한 개 이상).

 

- 멤버변수(클래스의 선언부에 정의된 변수)가 private상태이기 때문에 자손 클래스에서 상속된 조상 클래스의 멤버변수를    사용하지 못할 때에는 조상클래스의 생성자를 만들어서 'super(멤버변수)'의 형태로 사용해줘야 한다.

 

 

 

 

 

 

 

 

오버라이딩


 

- 조상클래스로부터 상속받은 메소드의 내용을 변경하는 것.

- 선언부는 조상의 선언부와 완전히 일치해야 함.

- 접근제어자는 조상클래스의 메소드보다 좁은 범위로 변경할 수 없다.

- 조상클래스의 메소드보다 많은 수의 예외를 선언할 수 없다.

- 조건

  1) 이름이 같아야 한다.

  2) 매개변수가 같아야 한다.

  3) 반환타입이 같아야 한다.

 

 

 

< 예제 >

public class BirdPlay {
 	public static void main(String s[]){
		Duck duck = new Duck();
		duck.setName("꽥꽥이");
		duck.fly();
		duck.sing();
		System.out.println(duck.toString());
		
		Sparrow sparrow = new Sparrow();
		sparrow.setName("짹짹");
		sparrow.fly();
		sparrow.sing();
		System.out.println(sparrow.toString());
		
		//=  String result = sparrow.toString();
		//   System.out.println(result);
	}
}

: 위의 기준을 만족하기 위한 클래스, 생성자 작성하기

 

1. 필요한 멤버변수 선언

2. get, set 메소드 정의

2. 객체가 만들어진 Duck, Sparrow 클래스 작성

3. 각 클래스에 fly(), sing(), toString() 메소드 정의

public class Duck {
	String name;
	int legs;
	int length;

	public void fly() {
		System.out.println("오리("+name+")는 날지 않습니다.");
	}
	
	public void sing() {
		System.out.println("오리("+name+")가 소리내어 웁니다.");
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public String toString() {
		String result = "오리의 이름은 "+name+" 입니다.";
		return result;
	}
}
public class Sparrow {
	String name;
	int legs;
	int length;
	
	public void fly() {
		System.out.println("참새("+name+")가 날아다닙니다.");
	}
	public void sing() {
		System.out.println("참새("+name+")가 소리내어 웁니다.");
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public String toString() {
		String result = "참새의 이름은 "+name+" 입니다.";
		return result;
	}
}

 

 

 

 

 

 

 


상속

 


: 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것

class child extends parent {

}

 

- 자손 클래스에 새로운 코드가 추가되어도 조상 클래스는 아무런 영향을 받지 않는다.

- 생성자와 초기화블럭은 상속되지 않는다. 멤버만 상속된다.

- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.

 

 

상속을 들어가기 전에 확실하게 알아야 할 개념정리

 

* 객체

: 값을 저장하기 위한 변수 묶음

 

* 인스턴스

: 클래스로부터 객체를 만드는 과정을 '인스턴스화'라고 하며, 어떤 클래스로부터 만들어진 객체를 인스턴스라고 한다.

 

* 생성자

: 생성자는 인스턴스가 생성될 때 호출되는 '인스턴스 초기화 메소드'이다.

 

 

 

<예제>

public class Prob2 {
	public static void main(String[] args){
		
		Drink coffee = new Drink("커피",1500,4);
		Drink tea = new Drink("녹차",1100,7);
		Alcohol wine = new Alcohol("와인", 5000, 3, 15.1);
		
		System.out.println("***** 매 출 전 표 ***** ");
		coffee.printTitle();
		coffee.printData();
		tea.printData();
		System.out.println();
		
		wine.printTitle();
		wine.printData();
		
		int sum = coffee.getTotalPrice()
				  + tea.getTotalPrice()
				  + wine.getTotalPrice();
		
		System.out.println();
		System.out.println("*** 총금액 " + sum + "원 ***");
	}
}

위의 조건을 만족하는 상속 클래스 작성하기

 

public class Drink {
	private String name;//삼풍명
	private int price; //단가
	private int count;//수량
	public Drink() {
		
	}
	public Drink(String name, int price, int count) {
		this.name = name;
		this.price = price;
		this.count = count;
	}
	public int getTotalPrice() { //금액(단가*수량)
		int sum = 0;
		sum = (price*count);
		return sum;
	}
	public void setTotalPrice(int price) {
		this.price = price;
	}
	public void printTitle() {//타이틀을 출력
		System.out.println("상품명  단가  수량  금액");
	}
	public void printData() {//상품의 정보를 출력
		System.out.println(name+"   "+price+"  "+count+"  "+getTotalPrice());
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
}
public class Alcohol extends Drink{
	private  double alcper;
	public Alcohol() {
		
	}
	public Alcohol(String name, int price, int count, double alcper) {
		super(name, price, count);
		this.alcper = alcper;
	}
	public double getAlcper() {
		return alcper;
	}
	
	public void printTitle() {//타이틀을 출력
		System.out.println("삼풍명(도수[%])  단가  수량  금액");
	}
	public void printData() { // private이기 때문에 메소드로 접근해야 함. Drink클래스에서도 get메소드 만들어주기
		System.out.println(getName()+"("+alcper+")"+"    "+getPrice()+"  "+getCount()+"  "+getTotalPrice());
	}
}

* printTitle(), printData() 메소드 오버라이딩하기(재정의하기).

댓글