[멋사 TIL] 13기 day7

이은서·2024년 12월 11일
0

멋사

목록 보기
8/11
post-thumbnail

상속의 속성심화

메소드 오버라이딩

  • 메서드의 이름은 물론 파라메터의 갯수나 타입도 동일해야 함
  • 주로 상위 클래스의 동작을 상속받은 하위 클래스에서 변경하기 위해 사용

Overloading vs. Overriding

똑같은 클래스 내에서 완전히 똑같은 메소드를 만들어낼 수 없지만(그럴 이유도 없고), 상속 관계에서 부모의 메소드를 자식의 메소드를 재정의하여 사용할 수 있다.
똑같은 클래스 내에서는 오버로딩으로, "한 메소드"가 다양한 입력값을 받을 수 있는 식으로 활용이 되는 것이고 오버라이딩은 함수를 바꿔서 쓰려는 것이다.

  • note.   타입이 달라도 이름이 같으면 오버라이딩!

| 메소드 상속받아 더 구현 |

public void print(){
  super.print();
  System.out.println("a");
}

필드 vs 메소드

오버라이딩 되었을 때

  • 필드는 항상 타입을 따르지만
  • 메소드는 무조건 자식 것을 쓴다.(타입 무관)

Parentpublic int getI()메소드를 가지고 있고, Childpublic int getI()메소드를 가지고 있다면

package family;

class Parent {
    int i = 5;

    public int getI() {
        return i;
    }
}
package family;

class Child extends Parent {
    int i = 10;   // 필드 오버라이딩

    public int getI(){ // 메소드 오버라이딩
        return i;
    }
}
package family;

public class Exam06 {
    public static void test(Parent p){
        System.out.println(p.i);
        System.out.println(p.getI());
    }

    public static void main(String[] args) {
        Parent pc = new Child();
        test(pc); 
        // 필드는 parent의 i=5, 메소드는 오버라이딩 된 getI() = 10  
    }
}

ChildgetI()메소드가 실행된다.



Object 클래스의 메소드들 활용하기

🔗 Java Docs    🔎 java api Object

코딩을 하다보면 이렇게 객체의 설계도, class에 구현해둔 필드•메소드들 외에 뜨는 equals(), hashCode()와 같은 것들이 있다. 이 아이들은 모두 Object 클래스의 메소드들이다.
Object 클래스는 왜 이 메소드들을 제공할까?

모든 클래스는 Object의 자손이다. 따라서 자식들인 모든 객체들은 이를 오버라이드해서 사용할 수 있다. Object가 이렇게 할 수 있도록 구현해둔 이유는 통일성 있게 출력하고 싶어서이다.

예를 들면, 세상에 있는 많은 객체들은 정보를 출력해보고 싶을 때가 있을 것이다. 이때 어떤 객체는 ~메소드로, 이 객체는 ~메소드로, ... 출력하기보다는 같은 방법으로 출력하는 편이 좋을 것이다. 그렇지 않는다면 정보를 보기 위해 사용해야 하는 메소드를 객체마다 매번 찾아야 할 것이기 때문이다. 변수는 출력하면 값이 나오지만, 객체는 값이 하나가 아니므로 이 정보를 보기 위해 저마다의 메소드가 만들어졌을 것이다. 따라서 Object 클래스는 정보를 보여주는 메소드 toString()을 정의해두어 사용하는 방법에 통일성이 있을 수 있게 했다.

  • object가 구현하고 있는 내용 대다수는 의미없는 내용: 구체적인 객체를 모르니까 당연하다. ➡️ 이걸 가져다가 오버라이드하여 구현하면 됨

equals()
주소값을 비교하고 있기 때문에 달라요 라고 출력
하지만 같아요라고 하고 싶을 때가 있음
toString()처럼 equals 메소드를 오버라이드해서 활용해보자

"세상에 같은 게 하나도 없다"가 철학이지만 "같은 것끼리 모아봐"가 안되므로 필요한 기능 : equals()

default: 메모리 공간이 다를 것이므로 다르다고 출력할 것이지만 값이 같다면 같다고 출력하도록 equals() 바꿔주기

같은 애니? 판단
equals : 하나하나
레퍼런스 데이터 타입은 주소를 담고 있기 때문에 주소를 비교하는 거임
그래서 같니 라는 걸 얻기 위한 메소드 가 필요했구나~
equals 오버라이드 안 해두면 계속해서 주소로 비교
자료구조 배울 때 더 참고

hashcode
: 객체의 값을 알고리즘을 이용해 숫자값으로 바꿔서 같은 값이면 같은 숫자값 리턴 아니면 숫자값이 서로 다르게 리턴
hashcode가 속도 더 빠름(더 빠르게 값 도출)

cf.
가급적 표준을 지키는 게 좋지만 기업 입장에서는 내 거가 더 특별해야 선택받으니까
(~는 ~이렇게 쓰는 게 더 편하고~)이런 게 있음
그래도 표준을 지키는 게 편하긴 함
데이터베이스도 마찬가지
기본적 쿼리문은 다 같은데 또 회사마다 다른 것들이 있긴 함



String은 불변 클래스이다.

불변 클래스란?
불변 클래스는 생성된 객체의 데이터를 수정할 수 없는 클래스다.

String str = "hello";

객체 = 생성된 메모리 상의 실체
이기 때문에 이 코드에서 객체는 "hello"이다. 불변 클래스 String에서 수정할 수 없는 건 바로 이 "hello"이다.

메모리상에서의 String
메모리에는 string값만 저장하는 공간이 존재한다. 메모리상에서 문자열이 너무 많이 생성되므로 더 효율적으로 관리할 방법을 제공하는 것이다.



String 타입과 primitive 타입의 비교

코드
Stringprimitive type int
String str1 = "hello";int num1 = 10;
String str2 = str1; // str1과 같은 객체를 참조int num2 = num1; // num1의 값을 복사
System.out.println(str1); // "hello"System.out.println(num1); // 10
System.out.println(str2); // "hello"System.out.println(num2); // 10
// str1을 변경 (새 객체 생성)// num1 값을 변경
str1 = str1.concat(" world");num1 = 20;
// 결과 확인// 결과 확인
System.out.println(str1); // "hello world"System.out.println(num1); // 20
System.out.println(str2); // "hello"System.out.println(num2); // 10

⭐이 num1 = 20;과 같았다면?

  • num2의 값은 num1을 따라 변하지 않는다.
  • 그러나 str2의 값은 str1과 같이 변해버렸을 것이다.

[str1, str2]는 참조변수로, 하나를 변경하면 모든 참조 변수가 영향을 받게 되지만,
[num1, num2]는 기본형변수로, 독립적인 값을 가지기 때문에
num1 값을 변경해도 num2는 영향을 받지 않는다.


package day07;

public class StringTest {
    public static void main(String[] args) {


        MyClass myClass = new MyClass();
        myClass.i  = 10;


        String str1 = "hello";

        String str2 = new String("hello");

        String str3 = new String("hell0");

        String str4 = "hello";
    }
}

new해서 만드는 것이 다소 비효율적
그럼에도 생성자가 존재하는 이유는 다양한 방법으로 string 만들고 싶기도 하기 때문



package day07;

public class StringTest04 {
    public static void main(String[] args) {
        // 다른 객체들의 일반적 방법이었다~
        String str = new String("Hello"); 
        // 그런데 String은 너무 많이 사용이 되므로 
        // 자바가 설계할 때 이렇게 쓸 수 있게 했다.
        String str2 = "hello"; 
        // str2가 참조하는 객체와 동일한 "hello" 객체를 참조하고 있는 것
        String str3 = "hello"; 

        
        // string 객체가 스스로 바뀌면 안되겠구나~
        // String 클래스가 가지고 있는 많은 메소드를 사용
        // 명시적으로 추가해두어야 한다.

        System.out.println(str3);
        System.out.println(str2=str2.toUpperCase());
        System.out.println(str2);

    }
}

str2=str2.toUpperCase()에서 아예 새로운 "HELLO"라는 객체가 생성된다.




추상클래스

필요성⭐(중요)

추상클래스의 필요성

추상클래스는 추상메소드를 가질 수 있다.
"동물?" "새?" "음식?" : 구체적이지 않다
기능구현이 어려운 애들은 추상적이기 때문
애매하다고 빼기에는, 새.노래하다()라고 쓸 수 없다.
구현하지 않으면 자식이 구현하는 메소드를 부모가 쓸 수 없다.
"내가 구현하기 좀 힘들어"하는 애들 앞에 abstract라고 써줌

추상메서드의 필요성

  • 강제성
    추상메서드를 가진 추상클래스를 상속받은 클래스는 반드시 메소드를 구현해야 한다는 강제성을 가진다.
    ↳ "꼭 있어야 해"라고 말을 해도 빼먹을 수 있는 것을 미연 방지 가능

  • 표준화
    다 ~방식으로 노래하게 될 것: 저마다 다르게 노래를 부르도록 하면 통일성이 없었을 것!
    원래 부모가 물려주지 않은 것들은 접근할 수 없었음
    그러나 추상메서드로라도 알고 있기 때문에 형변환 없이 자식의 메소드 사용하는 것이 가능

✏️ 새를 구현하려고 하는데 "짹짹" 할지 "뻐꾹"할지 모르기 때문에 추상 메소드를 만드는 것
✏️ 자바 api에도 이렇게 제공되고 있는 애들이 많음
↳ 객체 설계할 때에도 참고 가능!

이렇게 안 하면 결국 자식이 다 마지막에 구현해야 함.. 누군가는 구현해야 한다..
인스턴스화가 되지 않는다.(당연하지만~)

❗주의

  • 추상메서드 작성 시 abstract를 붙이면 구현부{} 붙이면 안됨
    (구현 안 하려고 추상메서드 사용하는 거니까!)
  • 추상메서드 가지고 있으면 클래스에도 abstract 붙여줘야



cf. Object 클래스의 toString() equals() : 추상메서드와 닮았다!!

Object는 왜 그럼 추상 클래스로 안 만들고, 추상 메소드로 안 만들고 구현해뒀을까?

추상 메소드는 강제성을 가지고 있기 때문에, 추상 메소드로 만들게 되면 모든 상속받은 자식들은 무조건 toString equals를 구현해야 하는데 모든 자식들이 이 둘이 필요하지 않음
구현하기 애매하지만 강제성까지는 필요 없을 때
필요에 따라서는 오버라이드해서 사용하고, 그렇지 않으면 쓰지 않도록


final

어디에 붙냐에 따라~

위치final
메소드final오버라이딩 불가(자식에서 수정 금지) / 오버로딩 가능🙆🏻‍♀️🙆🏻‍♂️🙆🏻
클래스final상속 불가(대를 끊겠다ㅋㅋ) : 당연히 오버라이딩도 불가
필드final상수다

cf1. Math 클래스에 붙어있는 final
악의적으로 사용해버리면 안 되기 때문에 붙어있다.

cf2. 메소드에 붙어있는 final
오버로딩은 가능! 이름은 같고 다른 메소드이기 때문에




기타 쫌쫌따리 지식

  • 메소드에 들어갈 때 모두 묵시적 형변환이 일어남
  • return : 돌아간다~
  • 문자열 조작: 문자열 Class
    ↳차를 차 클래스가 제일 잘 바꾸듯이

0개의 댓글