상속(업/다운캐스팅 추가예정), 오버라이딩(&virtual), 추상화

정제로·2023년 8월 16일
2

C#

목록 보기
19/30

번외

char형식을 Write로 출력하면?

일반적으로 char형식은 문자를 'a', 'b'... 이런식으로 ' '와 같이 저장을 하게 된다.

예제코드

using System;

namespace ConsoleApplication45
{
    class Program
    {
        static void Main(string[] args)
        {
            string str = "IamIronMan";
            char[] arr = str.ToCharArray();

            int n = 3;

            Console.WriteLine(str[n-1]);
            Console.WriteLine(arr[n-1]);
        }
    }
}

이 두 코드가 있다고 가정해보자.
str[n-1]arr[n-1]은 똑같은 값으로 출력된다!

이를 미루어 봤을때, str[n-1]로 출력을 하면 자동으로 char로 변환이 되어 출력이 된다는 것을 알 수 있다!

근데 왜 ' '이런식으로 작은 따옴표와 같이 출력되지 않는걸까?

찾아보니, 작은 따옴표는 생략이 되어 출력이 된다고 한다!
따라서 따옴표가 필요하면 '\'를 잘 사용하도록 하자


상속이란?

상속 (Inheritance)

  • 상위 클래스의 코드와 메서드등을 하위 클래스가 물려받아 사용
  • 상위 클래스는 부모클래스 라고불리고 하위클래스는 자식클래스라고 불림
  • C#에서 상속은 기본적으로 자식클래스에 1개만 적용할 수 있음
  • 다중상속은 클래스가 인터페이스를 상속받을때 가능하다.

예제

using System.Text;

namespace Baek_Jun
{
    public class Units
    {
        public void Move()
        {
            Console.WriteLine("두발로 걷는중...");
        }
        public void Attack()
        {
            Console.WriteLine("Unit 공격!");
        }
    }

    public class Marine : Units
    {

    }

    public class BattleCruiser : Units
    {

    }

    public class Base
    {
        static void Main()
        {
            /*
            Marine marine = new Marine();
            marine.Move();
            marine.Attack();

            BattleCruiser battleCruiser = new BattleCruiser();
            battleCruiser.Move();
            battleCruiser.Attack();
        }
    }
}

보다싶이 Units라는 클래스가 부모클래스가되어,
자식클래스인 Marine과 BattleCruiser라는 클래스가 부모클래스의 코드와 메서드를 이용하여,
객체를 생성해주니, 출력이 동일하게 출력된다!

근데... 배틀크루저는 두발로 걷는게 아니라 둥둥 떠다니는것 아닌가?
해서 아래와 같이 BattleCruiser클래스 안에 새로운 Move메서드를 만들어서
출력해보자

public class BattleCruiser : Units
{
	public void Move()
    {
    	Console.WriteLine("둥둥 떠다니는중");
    }
}


어라? 이상하게 출력이 잘만된다!
사실 이 문제는 자식클래스로 객체를 만들어 출력할때 발생하는게 아닌
부모클래스로 객체를 생성하여 출력할때 문제가 생긴다

using System.Text;

namespace Baek_Jun
{
    public class Units
    {
        public void Move()
        {
            Console.WriteLine("두발로 걷는중...");
        }
        public void Attack()
        {
            Console.WriteLine("Unit 공격!");
        }
    }

    public class Marine : Units
    {

    }

    public class BattleCruiser : Units
    {
        public void Move()
        {
            Console.WriteLine("둥둥 떠다니는중");
        }
    }

    public class Base
    {
        static void Main()
        {
           
            List<Units> list = new List<Units>();            
            list.Add(new Marine());
            list.Add(new BattleCruiser());

            foreach (Units unit in list) 
            { 
                unit.Move();
            }
        }
    }
}


보다싶이 list배열로 마린과 배틀크루저의 객체를 생성하여 Add후,
list안의 각 unit의 move메서드를 실행시키니 동일한 결과가 나오게 되었다.
분명 둥둥떠다니는중이라고 Move메서드를 변경해주었는데도!!

업캐스팅 개념 잡힌 후에 업로드 예정
다운캐스팅 추후에 업로드 예정

여기서 필요한것이....

오버라이딩!(virtual)

사용법은 간단하다.

  • 부모클래스의 재정의 될 여지가 있는 메서드에 virtual을 붙여준다
  • 굳이 자식클래스에서 해당 메서드를 재정의 할 필요는 없음
  • 자식클래스에서 재정의시 자식클래스의 메서드로 실행이됨
using System.Text;

namespace Baek_Jun
{
    public class Units
    {
        public virtual void Move()
        {
            Console.WriteLine("두발로 걷는중...");
        }
        public void Attack()
        {
            Console.WriteLine("Unit 공격!");
        }
    }

    public class Marine : Units
    {

    }

    public class BattleCruiser : Units
    {
        public override void Move()
        {
            Console.WriteLine("둥둥 떠다니는중");
        }
    }

    public class Base
    {
        static void Main()
        {
            List<Units> list = new List<Units>();            
            list.Add(new Marine());
            list.Add(new BattleCruiser());
           
            foreach (Units unit in list) 
            { 
                unit.Move();
            }
        }
    }
}

위와같이 무보클래스 메서드의 반환값 앞에 virtual을 붙여주고
자식클래스에서 해당 메서드를 재정의 하고자 하면 해당 메서드를 불러온 후 반환값 앞에 override를 붙여주면 된다

출력도 잘만 된다!
위와같이 굳이 재정의를 안해주어도 되고 재정의를 해주면 그 재정의된 메서드로 실행이 된다!

이와같이 재정의를 해도되고 안해도되는 virtual 함수가 있지만...
무조건 재정의를 해줘야만하는 함수도 존재한다!ㅠ

추상클래스!

  • 직접적으로 인스턴스 생성이 불가한 클래스이다
  • 주로 상속을 위한 기초클래스로 사용된다
  • 추상클래스는 abtract를 사용하여 선언되며, 추상abtract메서드를 포함할 수 있다
  • 추상 메서드는 무조건 자식클래스에서 구현해주어야함
  • abstract클래스를 abstract클래스에 상속키실수도 있다!
using System.Text;

namespace Baek_Jun
{
    public abstract class Degree
    {
        public virtual void Weather()
        {
            Console.WriteLine("덥다!");
        }
    }

    /* 불가!
    public class Degree
    {
        public abstract void Weather()
        {
            Console.WriteLine("덥다!");
        }
    }
    */

    public class Spring : Degree
    {
        public override void Weather()
        {
            Console.WriteLine("따뜻하다~");
        }
    }

    public class Summer : Degree
    {
    }

    public class print
    {
        static void Main()
        {
            List<Degree> list = new List<Degree>();
            list.Add(new Spring());
            list.Add(new Summer());
            //list.Add(new Degree());

            foreach (Degree degree in list)
            {
                degree.Weather();
            }
        }
    }
}

abstract를 사용하는 이유는 간단하다.

예를들어 동물이라는 부모클래스가 있다고 가정하자.
그리고 토끼, 사자라는 동물이 있다고 가정하자.
동물! 이라는 것은 추상적이지만
토끼, 사자는 굉장히 직관적이다.
추상적인 존재를 제재하지 않고 객체화 하면, 나중에 오류가 생겼을때, 어디서 잘못됐는지 모를때가 있다.

생각해보자. 협업중에 난 아무생각없이 animal이라는 클래스를 그냥 만들었는데,
다른 사람이 그 animal코드를 객체화 시켜서 코드가 엉켜 버그가 생겼다.
그럼 어떻게 해결해야하지?

일단!
에러와 버그는 수준이 다른 단어다.
에러는 빨간줄과같이 보이는 반면
버그는 코드에는 오류가 없지만, 실행했을때, 의도와 다른 방향으로 출력되는 것이다.

abstract는 버그를 방지하고자 사용하는것이다.
//list.Add(new Degree());
처럼 추상클래스를 객체화 하려하면 에러가 난다.
미연에 버그를 방지하는 것이다.

또, 일반 클래스에서 virtual을 사용하는것과
추상클래스에서 virtual을 사용하는것의 차이는 없다.

또 추상메서드를 일반 클래스에서 사용을 못한다

profile
초보자입니다.. 잘못된 정보, 달게 받겠습니다..

0개의 댓글

관련 채용 정보