번외
일반적으로 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)
예제
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메서드를 변경해주었는데도!!
여기서 필요한것이....
사용법은 간단하다.
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 함수가 있지만...
무조건 재정의를 해줘야만하는 함수도 존재한다!ㅠ
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을 사용하는것의 차이는 없다.또 추상메서드를 일반 클래스에서 사용을 못한다