공부/C#

추상 클래스, 추상 함수(abstract), 인터페이스(interface)

미다손 2016. 5. 9. 14:42

//추상 클래스, 추상 함수(abstract)

    abstract class Gun

    {

        public int damage = 1;    //변수 지정 가능

        public int ammo = 5;


        //virtual public void Fire() = 0;   //c++에서의 순수가상함수. 자식이 무조건 오버라이드해야 하는 함수.

        public abstract void Fire();    //추상 함수를 가지면 class도 추상 클래스 여야 함. 자식이 무조건 오버라이드 해야함.

    } 


 //인터페이스(interface)

    interface IReload   //순수가상함수만 가지는 class 비스무리한 거...

    {

        //함수만 가능하다. abstract class와는 다르게 변수는 들어갈 수 없다.

        //int i = 0; //에러 - 인터페이스는 필드를 포함할 수 없습니다.


        void Reload();    //일반 함수는 접근 제한자가 없으면 private였으나 

//interface는 무조건 public 이다.

        //void Reload(){};  //구현부가 있으면 안된다.

    }

//테스트용 interface1

    interface IScope

    {

        void Aim();

    }

//테스트용 interface2

    interface IAim

    {

        void Aim();

    }

//class에서 상속 받음

class Pistol : Gun, IReload, IScope, IAim    //class상속은 무조건 1개만 되지만, interface는 다중 상속 가능(정부 순수 가상 함수이기에...)

    {

        public Pistol()    //생성자

        {

            damage = 1;

        }


        public Pistol(int power)    //생성자 인자1개

        {

            damage = power;

        }


        //가상함수 오버라이드

        public override void Fire()    //class Gun 에 있는 virtual함수 

        {

            ammo -= 1;

            Console.WriteLine("탕. {0}의 데미지", damage);

        }


        //인터페이스 함수 구현은 override를 안해도 된다.

        public void Reload()    //interface IReload 에 있는 순수 가상 함수이다.

        {

            ammo = 10;

            Console.WriteLine("장전 완료. ammo : {0}", ammo);

        }


        //interface IScope와 IAim에 둘다 Aim()함수가 있다.

        //아래 함수 자체로도 에러는 안난다. 어짜피 둘 다 추상 함수(순수 가상 함수)이므로..

        public void Aim()

        {

            Console.WriteLine("조준");

        }


        //하지만 나눠 사용할 경우가 있다. 

        //아래처럼 인터페이스 명을 앞에 붙여 쓰면 된다.

        void IAim.Aim() //public은 안쓴다.

        {

            Console.WriteLine("그냥 조준");

        }


        void IScope.Aim()

        {

            Console.WriteLine("조준경으로 조준");

        }

}


//main class

    class Program

    {

        static void Main(string[] args)

        {

            Pistol myGun = new Pistol(5);

            myGun.Fire();

            myGun.Reload();

            myGun.Aim();


            IScope scope = myGun as IScope; //요런 캐스팅이 되는 작업은 느리므로 자주 안하는 것이 좋다. 

            //myGun 이 IScope를 상속 받았으면 scope에 myGun이 들어간다. 아니면 null.

            if(scope != null)

            {

                scope.Aim();

            }


            Pistol bigGun1 = new BigGun(5);

            bigGun1.QuickFire1();

            bigGun1.QuickFire2();


            BigGun bigGun2 = new BigGun(5);

            bigGun2.QuickFire1();

            bigGun2.QuickFire2();

            bigGun2.QuickFireOld();


            IReload reloadable = bigGun1;   //캐스팅

            reloadable.Reload();


            if(reloadable is BigGun)

            {

                Console.WriteLine("reloadable은 BigGun");

            }

}