πŸ“š[Java] λ‹€ν˜•μ„±, λΆ„μˆ˜μ˜ λ§μ…ˆ λ¬Έμ œν’€μ΄

텁텁·2025λ…„ 4μ›” 9일

λ‹€ν˜•μ„±

λ‹€ν˜•μ„±(Polymorphism)은 이름 κ·ΈλŒ€λ‘œ λ‹€μ–‘ν•œ ν˜•νƒœ, μ—¬λŸ¬ ν˜•νƒœλ₯Ό λœ»ν•œλ‹€.
ν”„λ‘œκ·Έλž˜λ°μ—μ„œ λ‹€ν˜•μ„±μ€ ν•œ 객체가 μ—¬λŸ¬ νƒ€μž…μ˜ 객체둜 취급될 수 μžˆλŠ” λŠ₯λ ₯을 λœ»ν•œλ‹€.


λ‹€ν˜•μ  μ°Έμ‘°

//λΆ€λͺ¨ 클래슀
public class Parent {
    public void parentMethod() {
        System.out.println("Parent.parentMethod"); }}

//μžμ‹ 클래슀
public class Child extends Parent {
    public void childMethod(){
        System.out.println("Child.childMethod"); }}

//λΆ€λͺ¨νƒ€μž… λ³€μˆ˜κ°€ μžμ‹ νƒ€μž…μ„ μ°Έμ‘°
public class PolyMain {
    public static void main(String[] args) {        
        //λΆ€λͺ¨ λ³€μˆ˜κ°€ μžμ‹ μΈμŠ€ν„΄μŠ€ μ°Έμ‘°(λ‹€ν˜•μ  μ°Έμ‘°)
        Parent poly = new Child();
        poly.parentMethod();
        
        //Child child1 = new Parent();
        //컴파일였λ₯˜ : μžμ‹μ€ λΆ€λͺ¨λ₯Ό 담을 수 μ—†λ‹€.
        
        //poly.childMethod();
        //μžμ‹μ˜ κΈ°λŠ₯을 ν˜ΈμΆœν•  수 μ—†λ‹€. 컴파일 였λ₯˜
}}
  • Parent νƒ€μž…μ˜ λ³€μˆ˜λŠ” λ‹€μŒκ³Ό 같이 μžμ‹ μΈ Parent λΏλ§Œμ•„λ‹ˆλΌ,

    μžμ‹ νƒ€μž… κ°μ²΄κΉŒμ§€ μ°Έμ‘°ν•  수 μžˆλ‹€.
    - Parent poly = new Parent();
    - Parent poly = new Child();
    - Parent poly = new Grandson(); // Child ν•˜μœ„μ— μ†μžκ°€ μžˆλ‹€λ©΄ μ΄λ˜ν•œ κ°€λŠ₯

  • λ°˜λŒ€λ‘œ μžμ‹μ€ λΆ€λͺ¨λ₯Ό 담을 수 μ—†λ‹€.

    • Child child1 = new Parent(); //컴파일 였λ₯˜ λ°œμƒ
  • μžλ°”μ—μ„œ λΆ€λͺ¨ νƒ€μž…μ€ μžμ‹ μ€ 물둠이고, μžμ‹ μ„ κΈ°μ€€μœΌλ‘œ λͺ¨λ“  μžμ‹ νƒ€μž…μ„
    μ°Έμ‘°ν•  수 있으며 이λ₯Ό λ‹€ν˜•μ  참쑰라고 ν•œλ‹€.

λ‹€ν˜•μ  참쑰의 ν•œκ³„

  • λ‹€ν˜•μ  μ°Έμ‘°λ₯Ό 톡해 λΆ€λͺ¨ νƒ€μž…μœΌλ‘œ μžμ‹ 객체λ₯Ό 담을 수 μžˆμ§€λ§Œ,
    λΆ€λͺ¨κ°€ κ°€μ§„ κΈ°λŠ₯(λ©”μ„œλ“œ)만 호좜 κ°€λŠ₯ν•˜λ‹€.

λ‹€μš΄μΊμŠ€νŒ…

μ•žμ„  ν•œκ³„μ μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„  ν˜ΈμΆœν•˜λŠ” νƒ€μž…μ„ μžμ‹μΈ Child νƒ€μž…μœΌλ‘œ κ°•μ œλ‘œ λ³€κ²½ν•˜λ©΄ λœλ‹€.

public class CastingMain1 {
    public static void main(String[] args) {
        //λΆ€λͺ¨ λ³€μˆ˜κ°€ μžμ‹ μΈμŠ€ν„΄μŠ€ μ°Έμ‘°(λ‹€ν˜•μ  μ°Έμ‘°)
        Parent parent = new Child();
        //단 μžμ‹μ˜ κΈ°λŠ₯은 ν˜ΈμΆœν•  수 μ—†λ‹€. 컴파일 였λ₯˜ λ°œμƒ
        //parent.childMethod();

        //λ‹€μš΄μΊμŠ€νŒ…(λΆ€λͺ¨νƒ€μž… -> μžμ‹νƒ€μž…)
        Child child = (Child) parent;
        child.childMethod(); //μ‚¬μš© κ°€λŠ₯
    }
}

μ‹€ν–‰μˆœμ„œ

Parent parent = new Child();
//Parent νƒ€μž…μ„ κ°€μ§„ Child 객체 생성
Child child = (Child) ;
//λ‹€μš΄μΊμŠ€νŒ…μ„ 톡해 λΆ€λͺ¨νƒ€μž…을 μžμ‹νƒ€μž…μœΌλ‘œ λ³€ν™˜ν•΄μ„œ λŒ€μž…
Child child = (Child) X001;
//참쑰값을 읽은 λ‹€μŒ μžμ‹ νƒ€μž…μœΌλ‘œ μ§€μ •
Child child = X001; //μ΅œμ’… κ²°κ³Ό
  • κ΄„ν˜Έμ™€ κ·Έ 사이에 νƒ€μž…μ„ μ§€μ •ν•˜λ©΄ νŠΉμ • νƒ€μž…μœΌλ‘œ ν˜•λ³€ν™˜ ν•  수 μžˆλ‹€.
    이λ₯Ό μΊμŠ€νŒ…μ΄λΌ ν•œλ‹€.
  • μΊμŠ€νŒ…μ„ ν•œλ‹€κ³  ν•΄μ„œ Parent parent의 νƒ€μž…μ΄ λ³€ν•˜μ§€λŠ” μ•ŠλŠ”λ‹€.
  • ν•΄λ‹Ή 참쑰값을 κΊΌλ‚΄κ³  κ·Έ 참쑰값이 Child νƒ€μž…μ΄ λ˜λŠ”κ²ƒ

    λ””ν…ŒμΌν•œ 흐름

    • new Child() β†’ νž™ μ˜μ—­ X001 λ²ˆμ§€μ— Child 객체 생성
    • Parent parent = X001; β†’ Parent νƒ€μž…μœΌλ‘œ μ°Έμ‘° (Parent νƒ€μž…)
    • Child child = (Child) parent; β†’ X001 κ·ΈλŒ€λ‘œ 볡사, 이λ₯Ό Child νƒ€μž…μœΌλ‘œ ν˜•λ³€ν™˜
    • κ²°κ΅­ β†’ Parent, Child λ‘˜ λ‹€ X001 μ£Όμ†Œ λ“€κ³  있음

μ—…μΊμŠ€νŒ…

public class CastingMain3 {
    public static void main(String[] args) {
        Child child = new Child();
        Parent parent1 = (Parent) child; //μ—…μΊμŠ€νŒ…
        Parent parent2 = child; //μ—…μΊμŠ€νŒ…μ€ μƒλž΅κ°€λŠ₯, μƒλž΅κΆŒμž₯

        parent1.parentMethod();
        parent2.parentMethod();
        //λ‘˜ λ‹€ μ‹€ν–‰κ°€λŠ₯
    }}
  • μ—…μΊμŠ€νŒ…μ€ JVM 이 μžλ™μœΌλ‘œ ν˜•λ³€ν™˜ ν•΄μ£ΌκΈ° λ•Œλ¬Έμ— μΊμŠ€νŒ…μ„ ν•  ν•„μš”κ°€ μ—†λ‹€.
    • μžμ‹μ€ λΆ€λͺ¨μ˜ νŠΉμ§•μ„ λ‹€ κ°–κ³  있음
    • JVM μž…μž₯μ—μ„œ 보면 μ•ˆμ „ν•¨
    • λΆ€λͺ¨κ°€ ν•„μš”ν•œλ° μžμ‹ μ€˜λ„ 아무 문제 μ—†μŒ
    • κ·Έλž˜μ„œ (Parent) μƒλž΅ κ°€λŠ₯
상황섀λͺ…μΊμŠ€νŒ… ν•„μš” μ—¬λΆ€
μ—…μΊμŠ€νŒ…(μžμ‹ β†’ λΆ€λͺ¨)μž‘μ€ νƒ€μž… -> 큰 νƒ€μž…μžλ™ ν˜•λ³€ν™˜, μΊμŠ€νŒ… μƒλž΅ κ°€λŠ₯
λ‹€μš΄μΊμŠ€νŒ…(λΆ€λͺ¨ β†’ μžμ‹)큰 νƒ€μž… -> μž‘μ€ νƒ€μž…λͺ…μ‹œμ  μΊμŠ€νŒ… λ°˜λ“œμ‹œ ν•„μš”

λ‹€μš΄μΊμŠ€νŒ…μ˜ 주의점

public class CastingMain4 {
    public static void main(String[] args) {
        //1λ²ˆμ½”λ“œ
        Parent parent1 = new Child();
        Child child1 = (Child) parent1;
        child1.childMethod(); //λ¬Έμ œμ—†μŒ

        //2λ²ˆμ½”λ“œ      
        Parent parent2 = new Parent();
        Child child2 = (Child) parent2; //λŸ°νƒ€μž„ 였λ₯˜ - ClassCastException
        child2.childMethod(); //μ‹€ν–‰ λΆˆκ°€
    }
}
  • Parent parent2 = new Parent(); λΆ€λͺ¨ νƒ€μž…μœΌλ‘œ 객체λ₯Ό μƒμ„±ν•œλ‹€.

    • λ©”λͺ¨λ¦¬ 상에 μžμ‹ νƒ€μž…μ€ μ‘΄μž¬ν•˜μ§€ μ•ŠμŒ
  • Child child2 = (Child) parent2; parent2 λ₯Ό Child νƒ€μž…μœΌλ‘œ λ‹€μš΄μΊμŠ€νŒ…

    • λ©”λͺ¨λ¦¬ 상에 Child 객체가 μ‘΄μž¬ν•˜μ§€μ•ŠμŒ > μ‚¬μš©λΆˆκ°€
  • μžλ°”μ—μ„  μ‚¬μš©ν•  수 μ—†λŠ” νƒ€μž…μœΌλ‘œ λ‹€μš΄μΊμŠ€νŒ… μ‹œ ClassCastException
    μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¨λ‹€.

    • μ˜ˆμ™Έ λ°œμƒ μ‹œ λ‹€μŒ λ™μž‘μ΄ μ‹€ν–‰λ˜μ§€ μ•Šκ³  ν”„λ‘œκ·Έλž¨μ΄ κ°•μ œλ‘œ μ’…λ£Œλœλ‹€.
    • λ”°λΌμ„œ child2.childMethod(); μ½”λ“œ μžμ²΄κ°€ μ‹€ν–‰λ˜μ§€ μ•ŠμŒ

instanceof

객체가 νŠΉμ • 클래슀둜 λ§Œλ“€μ–΄μ‘ŒλŠ”μ§€ 검사할 λ•Œ μ‚¬μš©

public class CastingMain5 {
    public static void main(String[] args) {
        Parent parent1 = new Parent();
        System.out.println("parent1 호좜");
        call(parent1);
        //Child μΈμŠ€ν„΄μŠ€κ°€ μ•„λ‹˜

        Parent parent2 = new Child();
        System.out.println("parent2 호좜");
        call(parent2);
        //Child μΈμŠ€ν„΄μŠ€κ°€ 맞음
    }

    private static void call(Parent parent){
        if(parent instanceof Child){
            System.out.println("Child μΈμŠ€ν„΄μŠ€κ°€ 맞음");
            Child child = (Child) parent;
        } else {
            System.out.println("Child μΈμŠ€ν„΄μŠ€κ°€ μ•„λ‹˜");
        }
    }
}
  • call(parent1);
    • instanceof child 둜 체크 -> false
    • "Child μΈμŠ€ν„΄μŠ€κ°€ μ•„λ‹˜" 좜λ ₯
  • call(parent2);
    • instanceof child 둜 체크 -> true
    • "Child μΈμŠ€ν„΄μŠ€κ°€ 맞음" 좜λ ₯
  • instanceof λ₯Ό μ‚¬μš©ν•˜λ©΄ 객체와 클래슀 μ‚¬μ΄μ˜ 상속 관계λ₯Ό μ‰½κ²Œ 확인할 수 μžˆλ‹€.

μ½”λ”© ν…ŒμŠ€νŠΈ μž…λ¬Έ

λΆ„μˆ˜μ˜ λ§μ…ˆ

문제
첫 번째 λΆ„μˆ˜μ˜ λΆ„μžμ™€ λΆ„λͺ¨λ₯Ό λœ»ν•˜λŠ” numer1, denom1, 두 번째 λΆ„μˆ˜μ˜ λΆ„μžμ™€ λΆ„λͺ¨λ₯Ό λœ»ν•˜λŠ” numer2, denom2κ°€ λ§€κ°œλ³€μˆ˜λ‘œ μ£Όμ–΄μ§‘λ‹ˆλ‹€.
두 λΆ„μˆ˜λ₯Ό λ”ν•œ 값을 κΈ°μ•½ λΆ„μˆ˜λ‘œ λ‚˜νƒ€λƒˆμ„ λ•Œ λΆ„μžμ™€ λΆ„λͺ¨λ₯Ό μˆœμ„œλŒ€λ‘œ 담은 배열을 return ν•˜λ„λ‘ solution ν•¨μˆ˜λ₯Ό μ™„μ„±ν•΄λ³΄μ„Έμš”.

일차적인 주제인 λΆ„μˆ˜μ˜ λ§μ…ˆμ„ κ΅¬ν•˜λŠ” 건 κ°„λ‹¨ν–ˆμ§€λ§Œ κΈ°μ•½λΆ„μˆ˜ λΌλŠ” 쑰건이 λ‚΄ 발λͺ©μ„ μž‘μ•˜λ‹€.
λΆ„μžμ™€ λΆ„λͺ¨μ˜ μ΅œλŒ€ κ³΅μ•½μˆ˜λ₯Ό ꡬ해야 ν•˜λŠ”λ° 이λ₯Ό κ΅¬ν•˜λŠ” λ°©λ²•μœΌλ‘œ μœ ν΄λ¦¬λ“œ ν˜Έμ œλ²•μ΄ μžˆλ‹€λŠ” 것을 μ•Œκ²Œλ˜μ—ˆλ‹€.

μœ ν΄λ¦¬λ“œ ν˜Έμ œλ²•μ΄λž€?
2개의 μžμ—°μˆ˜(λ˜λŠ” 정식) a, b에 λŒ€ν•΄μ„œ aλ₯Ό b둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€λ₯Ό rμ΄λΌν•˜λ©΄(단, a>b), a와 b의 μ΅œλŒ€κ³΅μ•½μˆ˜λŠ” b와 r의 μ΅œλŒ€κ³΅μ•½μˆ˜μ™€ κ°™λ‹€. 이 μ„±μ§ˆμ— 따라, bλ₯Ό r둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€ r'λ₯Ό κ΅¬ν•˜κ³ , λ‹€μ‹œ r을 r'둜 λ‚˜λˆˆ λ‚˜λ¨Έμ§€λ₯Ό κ΅¬ν•˜λŠ” 과정을 λ°˜λ³΅ν•˜μ—¬ λ‚˜λ¨Έμ§€κ°€ 0이 λ˜μ—ˆμ„ λ•Œ λ‚˜λˆ„λŠ” μˆ˜κ°€ a와 b의 μ΅œλŒ€κ³΅μ•½μˆ˜μ΄λ‹€.


  1. λ¨Όμ € 두 λΆ„μˆ˜μ˜ 합을 κ΅¬ν•œλ‹€.
  • λΆ„λͺ¨λΌλ¦¬ κ³±ν•œ ν›„ λΆ„μžλŠ” 각각 λ‹€λ₯Έ λΆ„λͺ¨μ™€ κ³±ν•œ 값을 λ”ν•œλ‹€.
int numer3 = (numer1*denom2)+(numer2*denom1); //λΆ„μž
int denom3 = denom1 * denom2; //λΆ„λͺ¨

  1. λΆ„μž, λΆ„λͺ¨μ˜ μ΅œλŒ€ κ³΅μ•½μˆ˜λ₯Ό κ΅¬ν•˜λŠ” λ©”μ„œλ“œ μž‘μ„±
  • μ΅œλŒ€κ³΅μ•½μˆ˜λ₯Ό κ΅¬ν•˜κΈ° μœ„ν•΄ μœ ν΄λ¦¬λ“œ ν˜Έμ œλ²• μ‚¬μš©
public static int getGcd(int p, int q){
            if (q == 0) return p;
            return getGcd(q, p % q);
}
  • μ½”λ“œμ˜ 흐름
    • int p λ₯Ό int q둜 λ‚˜λˆ„μ—ˆμ„ λ•Œ λ‚˜λ¨Έμ§€μ˜ 값이 0이면 return p;
    • μ•„λ‹ˆλΌλ©΄ λ‹€μ‹œ (q, p % q)둜 ν˜ΈμΆœν•΄μ„œ 과정을 λ°˜λ³΅ν•œλ‹€.
    • λ°˜λ³΅ν•˜λ‹€ 보면 λ‚˜λ¨Έμ§€κ°€ 0이 λ˜λŠ” μˆœκ°„μ΄ μ˜¨λ‹€.
    • κ·Έ λ•Œ 남은 p의 값이 λ°”λ‘œ μ΅œλŒ€κ³΅μ•½μˆ˜μ΄λ‹€.

  1. ν•΄λ‹Ή 값을 κΈ°μ•½λΆ„μˆ˜λ‘œ λ§Œλ“ λ‹€.
    • μ΅œλŒ€κ³΅μ•½μˆ˜λ₯Ό λΆ„μž, λΆ„λͺ¨μ— 각각 λ‚˜λˆ„μ–΄μ€€λ‹€.
    • μ „μ²΄μ½”λ“œλŠ” 이렇닀.
class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) {
        int[] answer = {};
        answer = new int[2];
        int numer3 = (numer1*denom2)+(numer2*denom1);
        int denom3 = denom1 * denom2;
                
        int gcd = getGcd(numer3, denom3);
        
        answer[0] = numer3/gcd;
        answer[1] = denom3/gcd;
        
        return answer;
    }
    
    public static int getGcd(int p, int q){
            if (q == 0) return p;
            return getGcd(q, p % q);
    }
}

λΉˆμ•½ν•œ 머리λ₯Ό 아무리 ꡴렀봐도 μ΅œλŒ€κ³΅μ•½μˆ˜λ₯Ό κ΅¬ν•˜λŠ” 방식을 μž‘μ„±ν•  수 μ—†μ—ˆλ‹€...
μœ ν΄λ¦¬λ“œ ν˜Έμ œλ²• 도 생전 처음 λ“€μ–΄λ΄€λ‹€. 😭😭😭
μž…λ¬Έμ—μ„œ λ§‰νžˆλŠ” λ°”λžŒμ— 진도가 λ‚˜μ•„κ°€μ§ˆ λͺ»ν•΄ 였늘의 λ§ˆλ¬΄λ¦¬λŠ” μŠ¬ν””μœΌλ‘œ λ¬Όλ“€μ—ˆλ‹€.
내일은 쑰금 더 μ •μ§„ν•  수 있기λ₯Ό λ°”λž€λ‹€.

profile
μ°¨κ·Όμ°¨κ·Ό

0개의 λŒ“κΈ€