Acorn academy 12/06 클래스들의 관계

Bae Seong Jun·2023년 12월 6일

Acorn academy

목록 보기
14/70

초기화 블록 - 140p

개념 :
클래스에서 생성자와 비슷한 역할의 초기화 작업을 할 수 있는 2가지 블록이 제공된다. 1) 인스턴스 초기화 블록

  • 인스턴스 변수의 초기화에 사용할 수 있다. - 객체생성 할 때마다 수행된다. - 일반적으로 생성자를 사용하기 때문에 잘 사용되지 않는다. - 생성자보다 인스턴스 초기화 블록이 먼저 수행된다.

static 초기화 블럭

개념 :
static 초기화 블록

  • static 변수의 초기화 및 프로그램 시작시 초기화 작업이 필요한 경우에 사용한다. - 프로그램 시작시 단 한번 수행된다. - static 변수들이 생성된 후에 바로 static 초기화 블록이 static 변수들을 초기화한다.
  • 궁금점 : static 초기화 블럭이 실행되는 정확한 경우 (무조건 최초 1번만?)

Date함수 임포트 및 호출 - 내부 메소드 사용 위해서는 임포트 및 객체성생 필요
Math.random 객체 생성할 필요 없이 사용가능한 static 메소드? 클래스?
일단 Math클래스는 java.lang에 포함되어있어서 임포트가 필요없다.

import java.util.Date;

public class Test2 {
	public static void main(String[] args) {
		Math.random();
		Date d = new Date();
	}
}

final 키워드

개념

  • 클래스에 사용하면 상속이 불가능하다. 대표적인 클래스가 java.lang.Math 클래스이다. 상속 관련 내용은 6장에서 살펴보도록 한다.
  • 변수에 사용하면 값 변경이 불가능하다. 따라서 상수가 되며 변수와 구별하기 위해서 일반적으로 대문자로 표현한다.

상수는 일반적으로 다음 형식으로 표현한다. public static 지정자를 사용하여 외부에서
객체생성 없이 클래스이름으로 쉽게 접근 가능하도록 구현한다

public static final 데이터형 상수 = 값

싱글톤 디자인 패턴

예)
은행관리 시스템
은행객체 1개 (반드시 1개의 객체만 생성, 사용하도록 작성 )
계좌객체
100개 (new * 100개)

개념 :
1. private) 기본생성자
2. private) 내부 객체 생성 (static객체)(기본생성자 이용)
3. public) 내부에서 만든 static 객체를 외부로 반환해주는 함수를 하나 만든다.

형식 예제

형식 +
메인에서 하나의 객체를 여러 변수에 할당받고 멤버변수 name을 변경시 서로 다른 변수에서 name 값이 다른지 확인하는 코드
Bank.java

package com.banl;

public class Bank {
	
	private String name;

	private static Bank b=new Bank(); //2
	
	private Bank() {} //1
	
	public static Bank getBank() {
		return b;
		//3
	}

	
	public String getName() {
		return name;
	}

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

Test1.java

import com.banl.Bank;

public class Test1 {
	public static void main(String[] args) {
		Bank b1 = Bank.getBank();
		System.out.println(b1);
		
		Bank b2= Bank.getBank();
		System.out.println(b2);
		b1.setName("kb저축");
		System.out.println(b2.getName());
	}
}

출력화면

  • static 객체는 멤버변수도 다 static?

싱글톤 개념 4가지와 static 정독필요


클래스들의 관계

< 목차 >
클래스들의 관계
상속
접근 지정자
(중요)메서드 오버라이딩
(중요)다형성
Object 클래스
UML 관계

클래스들의 관계

개념 :

has a 관계

프로젝트명 : 07Day0_Has_Relation
개념 :
하나의 객체를 멤버변수로 갖는 객체

만약 매개변수를 전당하는 생성자를 클래스 내부에 안썼다면
클래스의 get객체 메소드 호출시 발생하는 문제?

	public Student(String string, int i, String string2, Parent p1) {
		// TODO Auto-generated constructor stub
	}

매개변수를 받아서 저장하는 구문이 없는 생성자가 클래스에 정의되어 있고
이 생성자를 통해서 객체를 생성할 경우 전달한 값들이 저장되지 않아서 기본데이터값들로 저장이 될 것이다. 그럼 getter 메소드로 객체의 객체멤버변수를 가져올 때 null을 반환.
만약 이 null에 메소드체인을 걸면 nullPoint 오류가 발생할 것으로 추정된다.

실행결과 예상과 같은 에러가 발생.
메인

public class Test {
	public static void main(String[] args) {
		Parent p1 = new Parent("AA", 50);
		Student stu = new Student("홍길동", 10, "서울", p1);
        
		Parent parent = stu.getParent();
		System.out.println(parent.getpName();
	}

Student 클래스

public class Student {
	
	private String name;
	private int age;
	private String addr;
	//has a 관계
	private Parent parent;
	
	public void setParent(Parent parent) {
		this.parent = parent;
	}
	public Parent getParent() {
		return this.parent;
	}
	
	
//	public Student(String name, int age, String addr, Parent parent) {
//		super();
//		this.name = name;
//		this.age = age;
//		this.addr = addr;
//		this.parent = parent;
//	}
	
    // 전달받은 값을 멤버변수에 저장하는 구문이 없는 생성자.
    // 이러면 해당 객체의 멤버객체에 접근하려할 때 주소값이 없고 null이 있으니 null이 가르키는 값이 없다는 뜻의 nullPointer Error가 발생한다.
	public Student(String string, int i, String string2, Parent p1) {
    }

워크샵 4-문제8 : 카페 워크샵. 난이도 상. 상당히 좋은 문제니 여러번 만들어보는 것을 추천

  • 위 워크샵 문제에 싱글톤 디자인 패턴 적용까지.

is a 관계

상속

개념:
부모 class b가 이름, 나이가 있고
A class가 부모class b를 상속받고있다면
A는 이름, 부모를 사용할 수 있다.

모든 클래스의 부모 클래스는 Object 클래스
객체 생성시 부모 객체들이 먼저 생성된다
A객체 생성시
Object -> 부모b ->a 순서로 객체가 생성된다.

객체들 간에 is a 관계가 성립되면 자바의 상속기법을 적용시킬 수 있다. 자바 상속의 특징은 다음과 같다.
§ 객체 간에 is a 관계가 성립되어야 한다.
§ 부모클래스의 멤버(인스턴스 변수, 메서드)를 자식클래스가 선언 없이 사용 가능하다. 단
부모 멤버중에서 private로 지정한 멤버와 생성자는 상속이 불가능하다.
§ 자바는 단일 상속 (Single Inheritance) 만 지원한다.
§ 상속을 UML 표기법으로 을 이용한다. (실선을 이용한 삼각형)
§ 상속을 자바코드에서는 extends 키워드로 표현한다.
§ API 및 사용자가 만든 클래스들은 모두 상속 관계인 계층구조로 되어있다. 가장 상위에
있는 클래스는 java.lang.Object 클래스이며 최상위 클래스라고 부른다. 따라서 모든 클
래스는 Object 클래스를 자연스럽게 상속받는다.

모든 메소드 뒤에는 extends Object가 자동으로 추가되어있다.


오버라이딩 : 부모에있는 함수를 자식에서 재정의하여 쓰는 것
오버로딩 : 이름이 같은 함수의 매개변수 차이를 두어 만드는 것
우클릭 -> source -> override에서 오버라이딩 자동생성이 가능하다.


super() : 부모의 기본생성자를 호출한다.

또한 super();는 자식 기본생성자 호출시 첫 줄에 자동으로 생성됨.
super()생략가능.
만약 부모의 기본생성자가 없다면 오류가 발생.

super() 안에 부모에 있는 특정 생성자와 동일한 형태로 매개변수로 기입하면 해당 생성자를 호출한다.

super 키워드

일반적으로 다음 2가지 경우에 사용된다.

  1. 부모클래스의 멤버와 자식클래스의 멤버가 이름이 동일한 경우 super.부모멤버 형식으로 표현한다. (이렇게 안쓴다 거의)

2(중요). 자식클래스에서 명시적으로 부모 생성자를 호출하는 경우 super([인자값]) 형식으로 사용하며 인자값은 없거나 여러 개가 가능하다. 주의할 점은 반드시 자식 생성자의 첫 라인에서 호출해야 된다.

참고로 상속받은 멤버변수들은 this.으로도 사용할 수 있음.

접근지정자 ( Access Modifier )

개념:

메서드 오버라이딩 ( method overriding ) (중요)

= 재정의
필수 요건 : 상속된 상태. 하위클래스가 상위클래스의 메소드를 재정의
규칙 :

부모
public void test(int a){}

자식
@override
public void test(int a){
함수 내용만 변경
}

개념 :
일반적으로 상속 관계시 부모 클래스의 메서드를 하위 클래스에서는 조건 없이 사용 가능하
다. 하지만 하위 클래스에서 부모 클래스의 메서드를 재정의해서 사용할 수도 있는데 이렇
게 재정의된 메서드를 overriding 이라고 부른다. 주의할 점은 오버로딩(overloading)과
구별할 수 있어야 된다. 메서드 오버라이딩 규칙은 다음과 같다.
§ 상속이 전제되어야 한다.
§ 메서드 이름이 반드시 동일해야 된다.
§ 메서드 리턴타입이 반드시 동일해야 된다. 단, 상속관계인 경우에는 작은 타입으로 재정
의 가능하다.
§ 메서드 인자 리스트가 반드시 동일해야 된다.
§ 접근 지정자는 부모의 레벨보다 같거나 확대만 가능하다.
§ 예외 클래스는 부모의 클래스보다 계층적으로 같거나 하위 클래스만 사용 가능하다.
§ static, final, private 지정자를 가진 메서드는 오버라이딩이 불가능하다.

다형성 ( Polymorphism ) (매우 중요)

이 방법들을 프로그램 코드에서 정말 자주 씀.
다형성 - 폴리몰피즘
: 부모 클래스 타입의 변수로 자식 클래스를 저장할 수 있다.
1) 상속관계가 아닌 경우
Emp Manager
Emp m = new Manager() -- 안됨

2)상속관계인 경우
Manager extends Emp
1) Manager m = new Manager();
2) Emp m2 = new Manager(); // 부모타입 변수에 자식 객체 저장 == 다형성
Emp - name, age
Manager - address
m2는 부모클래스 변수인 name, age를 사용할 수 있다,
하지만 address는 접근이 불가능하다.
address 사용을 위해서는 자식 타입으로 형변환을 해주어야함.
((Manager)m2).address = '제주'
이런 식으로 명시적으로 형변환을 해줘야 사용가능하다.

즉, 상속관계의 계층구조에서 상위타입의 변수로 모든 하위타입을
참조할 수 있는 특성을 ‘다형성’이라고 한다.

  • 의문점 : 부모타입에 자식타입 저장. 근데 자식이 부모꺼 오버라이딩했으면 오버라이딩된 자식 메소드를 사용. 도대체 왜?? -> 뒤에 기술

< 요약 >
1. 자식은 부모에 그냥 저장됨
2. 자식에 있는 것들을 사용하고싶으면 형변환을 하고 사용해라

  1. Object타입으로 모든 객체의 저장이 가능하다.

오버라이딩 된 함수에 대해 (상상당당히히 중요)

부모타입에 저장된 자식객체는 자식에 접근을 못한다.
하지만 만약에 부모객체 메소드가 있고 자식객체에서 오버라이딩한 상태라면
해당 메소드를 쓸 때 부모객체의 메소드를 사용하지만 오버라이딩된 실제 객체의 오버라이딩 메소드가 호출된다.

왜 중요한 개념인가? :
예를들면
부모의 자식으로 3개 타입의 객체가 있다. 각각 100개씩
이 여러개의 전체 데이터를 출력하고싶다.
다형성을 이용하면 부모타입의 배열에 이 3개 타입의 객체를 각각 100개씩 다 때려넣어서 저장할 수 있다.
그리고 자식에서 출력할 함수를 부모 함수 오버라이딩 구현해두면
부모 배열 하나에 자식객체를 저장하고 메소드까지 편하게 사용가능.

// 1. 다형성을 이용한 부모 타입 배열에 자식 객체 저장 가능
// 2. 자식에서 출력함수를 부모 함수 오버라이딩 구현 ex) getEmployee
// 따라서 정말 편해짐.

다형성을 이용한 메서드 파라미터 지정하기

  • 매개변수 같은 상황에도 해당된다
    emp가 부모 Manager Engineer 자식
    아래 코드에 change클래스의 객체로 받는 데이터의 타입이 Employee인데
    다른 타입으로 인자를 전달해도 오류가 없음
    이유는 부모데이터타입이라 다형성에 의해 자식타입은 문제없이 저장된 것임.

public class Test2 {
	public void change(Employee e) {
		
	}
	
	public static void main(String[] args) {
		Employee e = new Employee();
		Manager m = new Manager();
		Engineer en = new Engineer();
		Test2 t = new Test2();
		t.change(e);
		t.change(m);
		t.change(en);
		
	}
}

만약 상속관계가 아니라면 아래처럼 만들어줘야한다.

package com.test;

public class Test {
	public void change(Employee e) {
		
	}
	public void change(Manager e) {
		
	}
	public void change(Engineer e) {
		
	}
	
	public static void main(String[] args) {
		Employee e = new Employee();
		Manager m = new Manager();
		Engineer en = new Engineer();
		Test t = new Test();
		t.change(e);
		t.change(m);
		t.change(en);
		
	}
}

단일상속 : 하나의 클래스는 하나만 상속받을 수 있다.

내일은 다형성 매개변수 연습할 차례

profile
코딩 프로?

0개의 댓글