Wanna be Brilliant Full-Stack Developer

C# WINFORMS 상속 및 접근제어 #1 본문

Some Memos/C#

C# WINFORMS 상속 및 접근제어 #1

Flashpacker 2023. 4. 13. 10:29

CBASE라는 클래스를 만들었는데 직접적으로 사용하지는 않을것이다.

나중에 CBASE에 있는것들을 상속받아서 COneCycle이라는것을 만들것이다.

CCycle도 CBASE에한테 상속을 받아서 하나 만들것이고

CCAR은 CCYCLE한테 상속을 받아서 만들것이다.

위에있는것들이 부모클래스이고 밑에 있는것들은 자식 클래스이다!

부모클래스에 있는것들을 그대로 쓰기 때문에 재사용 및 확장에 용이하고

코드를 줄일 수가 있다. 

근데 부모에 있는 내용을  자식한테 모든걸 보여줄필요는 없다.

화면에다가 뿌릴려고 할때도 클래스 안에 있는 내용들을 전부다 보여주면 양이 너무 많아 질수도 있다.

앱에만 보여줄 수 있는 부분이나 가져다쓸수 있는부분을 제한을 시킨다.

접근 제어라는 부분들이 프로그램을 처음할때부터 익숙하게 쓰고 있었을것이다. 

 

항상쓰는건데 protect , private , public을 왜쓰는지 설명하기 위해서 이런 내용들을 배울것이다.

 

클래스 외부에서, 상속받은 클래스에서 접근을 제한하기 위한것이다.

 

CBASE 안에는 이름같은것들 밖에 없는데 근데 가져다 쓸 수 있다.

상속을 다른데에도 받아서 조금 변형해서 만들 수 도 있다!

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Inheritance
{
    internal class CBase
    {
        public string strName;

        public Pen _Pen;

        public CBase()
        {
            _Pen = new Pen(Color.Aqua);
        }

    }
}

이렇게 클래스를 만들었는데?!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Inheritance
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnOneCycle_Click(object sender, EventArgs e)
        {
            Graphics g = pMain.CreateGraphics();

            Pen p = new Pen(Color.Aqua);

            g.DrawRectangle(p, 50, 50, 100, 150);
        }
    }
}

여기서 쓰기 위해서는? 

근데 여기서 _Pen을 쓸필요가 없기 떄문에 Pen을 내부에서만 쓰겠다!

외부에서는 Pen 을 알필요가 없을때는? 

 internal class CBase
    {
        public string strName;

        private Pen _Pen;

        public CBase()
        {
            _Pen = new Pen(Color.Aqua);
        }

    }

이렇게 private를 하는경우에는 저 클래스 안에서만 쓸 수가 있다.

그러면 protected와 private과 같은거 아니냐 물어볼 수 있지만?!

차이점은 무엇인가? 상속받은 애들에 대해서는 protected는 볼수가 있지만

private은 안에서만 볼수가 없다.

protedcted는 상속을 하지 않으면 거의 볼일이 없는 접근제어자라고 생각하면 된다.

 

그러면 C#에서는 상속을 어떻게 하는가?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Inheritance
{
    class COneCycle : CBase
    {

    }
}

 

: (땡떙)만 붙이고 상속받을 클래스 이름을 적으면 된다.

 

여기서 생성자를 하나 만들어서 생성자에다가 그냥 사용하는것이 아니라

이름을 불러올것이라서 string sName이라는걸 받아오게 만들것이다.

sName이니까 이름을 사용할것인데 원래는 위에다가 이름을 정의 해야하는데?!

그런데 지금 상속을 받았기 때문에 저 이름이 있다고 생각하면 된다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Inheritance
{
    class COneCycle : CBase
    {
        public COneCycle(string sName) 
        { 
            strName = sName;
        }

    }
}

상속은 이러한 장점이 있다. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace Inheritance
{
    class COneCycle : CBase
    {
        public COneCycle(string sName) 
        { 
            strName = sName;
            _Pen = new Pen(Color.WhiteSmoke,3);
        }

    }
}

상속받은 아이들은 정의하는 과정을 다 제쳐두고 

그냥 쓰는것만 있다.

이렇게 하는일이 줄어든다는 것이다. 

Base에 다가 이름에다가 pen을 넣어놓고 Fom1 메인으로 ConeCyle을 생성할때  이름을 넣어놨고

펜의 색상과 굵기도 넣어놨다.

 

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;


namespace Inheritance
{
    internal class CCycle : CBase
    {
        public Rectangle _rtCircle1;   //바퀴
        public Rectangle _rtCircle2;   //바퀴
        public Rectangle _rtSquare1;   // 몸통

        public CCycle(string sName)
        {
            strName = sName;
            _Pen = new Pen(Color.Black, 3);

            _rtCircle1 = new Rectangle(30, 150, 120, 120);
            _rtCircle2 = new Rectangle(210, 150, 120, 120);
            _rtSquare1 = new Rectangle(60, 90, 240, 60);

        }


        public Pen fPenInfo()
        {
            // _Pen = new Pen(Color.WhiteSmoke, 3);

            return _Pen;
        }

    }
}

또다른 클래스를 만들었다! 그리고 또 부모클래스에게 상속을 받았다. 

부모는 여러명의 자식을 가질 수 있다!

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;


namespace Inheritance
{
    internal class CCar : CCycle
    {
        public Rectangle _rtSquare2;   // 몸통

        public CCar(string sName) : base(sName)
        {
            strName = sName;
            _Pen = new Pen(Color.Blue, 3);

            _rtCircle1 = new Rectangle(30, 150, 120, 120);
            _rtCircle2 = new Rectangle(210, 150, 120, 120);
            _rtSquare1 = new Rectangle(60, 90, 240, 60);
            _rtSquare2 = new Rectangle(60, 90, 240, 60);

        }



    }
}

이렇게 상속하는 이름만적어주면 된다!

움직이는건 Point함수에서 Location을 통해 위치와 좌표를 가져올 수 가 있다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;


namespace _13.Inheritance
{
    /// <summary>
    /// CBase를 상속 받은 외발 자전거 클래스
    /// </summary>
    class COneCycle : CBase
    {
        public Rectangle _rtCircle1;  // 바퀴1
        public Rectangle _rtSquare1;  // 몸통1

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="sName"></param>
        public COneCycle(string sName)
        {
            strName = sName;  // 클래스를 생성 할 때 이름을 가져와서 strName에 넣어 줌
            _Pen = new Pen(Color.WhiteSmoke, 3);  // 펜에 대한 색상과 굵기를 설정

            _rtCircle1 = new Rectangle(120, 150, 120, 120);  // 바퀴1에 대한 위치 및 크기를 설정
            _rtSquare1 = new Rectangle(150, 30, 60, 120);  // 몸통1에 대한 위치 및 크기를 설정
        }

        /// <summary>
        /// 설정 되어 있는 Pen에 대한 정보를 반환
        /// </summary>
        /// <returns></returns>
        public Pen fPenInfo()
        {
            //_Pen = new Pen(Color.White, 3);
            return _Pen;
        }

        /// <summary>
        /// 외부에서 그림의 위치를 이동시키는 함수를 호출
        /// </summary>
        /// <param name="iMove"></param>
        public void fMove(int iMove)
        {
            fCircle1Move(iMove);
            fSquare1Move(iMove);
        }

        /// <summary>
        /// 바퀴1의 위치를 가져와서 X 위치값을 이동 시키고 다시 바퀴1에 위치 정보를 넣어줌
        /// </summary>
        /// <param name="iMove"></param>
        protected void fCircle1Move(int iMove)
        {
            Point oPoint = _rtCircle1.Location;
            oPoint.X = oPoint.X + iMove;
            _rtCircle1.Location = oPoint;
        }

        /// <summary>
        /// 몸통1의 위치를 가져와서 X 위치값을 이동 시키고 다시 바퀴1에 위치 정보를 넣어줌
        /// </summary>
        /// <param name="iMove"></param>
        protected void fSquare1Move(int iMove)
        {
            Point oPoint = _rtSquare1.Location;
            oPoint.X = oPoint.X + iMove;
            _rtSquare1.Location = oPoint;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace _13.Inheritance
{
    class CCycle : CBase
    {
        public Rectangle _rtCircle1;  // 바퀴1
        public Rectangle _rtCircle2;  // 바퀴2
        public Rectangle _rtSquare1;  // 몸통1

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="sName"></param>
        public CCycle(string sName)
        {
            strName = sName;  // 클래스를 생성 할 때 이름을 가져와서 strName에 넣어 줌
            _Pen = new Pen(Color.Black, 3);  // 펜에 대한 색상과 굵기를 설정

            _rtCircle1 = new Rectangle(30, 150, 120, 120);  // 바퀴1에 대한 위치 및 크기를 설정
            _rtCircle2 = new Rectangle(210, 150, 120, 120);  // 바퀴2에 대한 위치 및 크기를 설정
            _rtSquare1 = new Rectangle(60, 90, 240, 60);  // 몸통1에 대한 위치 및 크기를 설정
        }

        /// <summary>
        /// 설정 되어 있는 Pen에 대한 정보를 반환
        /// </summary>
        /// <returns></returns>
        public Pen fPenInfo()
        {
            return _Pen;
        }

        /// <summary>
        /// 외부에서 그림의 위치를 이동시키는 함수를 호출
        /// </summary>
        /// <param name="iMove"></param>
        public void fMove(int iMove)
        {
            fCircle1Move(iMove);
            fCircle2Move(iMove);
            fSquare1Move(iMove);
        }

        /// <summary>
        /// 바퀴1의 위치를 가져와서 X 위치값을 이동 시키고 다시 바퀴1에 위치 정보를 넣어줌
        /// </summary>
        /// <param name="iMove"></param>
        protected void fCircle1Move(int iMove)
        {
            Point oPoint = _rtCircle1.Location;
            oPoint.X = oPoint.X + iMove;
            _rtCircle1.Location = oPoint;
        }

        /// <summary>
        /// 바퀴2의 위치를 가져와서 X 위치값을 이동 시키고 다시 바퀴1에 위치 정보를 넣어줌
        /// </summary>
        /// <param name="iMove"></param>
        protected void fCircle2Move(int iMove)
        {
            Point oPoint = _rtCircle2.Location;
            oPoint.X = oPoint.X + iMove;
            _rtCircle2.Location = oPoint;
        }

        /// <summary>
        /// 몸통1의 위치를 가져와서 X 위치값을 이동 시키고 다시 바퀴1에 위치 정보를 넣어줌
        /// </summary>
        /// <param name="iMove"></param>
        protected void fSquare1Move(int iMove)
        {
            Point oPoint = _rtSquare1.Location;
            oPoint.X = oPoint.X + iMove;
            _rtSquare1.Location = oPoint;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace _13.Inheritance
{
    class CCar : CCycle
    {
        public Rectangle _rtSquare2;  // 몸통2

        /// <summary>
        /// 생성자 : 상속받은 CCycle의 생성자를 가져옴
        /// </summary>
        /// <param name="sName"></param>
        public CCar(string sName) : base(sName)
        {
            strName = sName;  // 클래스를 생성 할 때 이름을 가져와서 strName에 넣어 줌
            _Pen = new Pen(Color.Blue, 3);  // 펜에 대한 색상과 굵기를 설정

            _rtCircle1 = new Rectangle(60, 180, 90, 90);  // 바퀴1에 대한 위치 및 크기를 설정
            _rtCircle2 = new Rectangle(210, 180, 90, 90);  // 바퀴2에 대한 위치 및 크기를 설정
            _rtSquare1 = new Rectangle(90, 30, 180, 90);  // 몸통1에 대한 위치 및 크기를 설정
            _rtSquare2 = new Rectangle(30, 120, 300, 60);  // 몸통2에 대한 위치 및 크기를 설정
        }

        /// <summary>
        /// 외부에서 그림의 위치를 이동시키는 함수를 호출 (상속받은 함수 중 같은 함수가 있기 때문에 new로 생성)
        /// </summary>
        /// <param name="iMove"></param>
        public new void fMove(int iMove)
        {
            fCircle1Move(iMove);
            fCircle2Move(iMove);
            fSquare1Move(iMove);

            fSquare2Move(iMove);
        }

        /// <summary>
        /// 몸통2의 위치를 가져와서 X 위치값을 이동 시키고 다시 바퀴1에 위치 정보를 넣어줌
        /// </summary>
        /// <param name="iMove"></param>
        protected void fSquare2Move(int iMove)
        {
            Point oPoint = _rtSquare2.Location;
            oPoint.X = oPoint.X + iMove;
            _rtSquare2.Location = oPoint;
        }

    }
}
using _13.Inheritance;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Inheritance
{
    public partial class Form1 : Form
    {
        COneCycle _cOC;
        CCycle _cC;
        CCar _cCar;
        public Form1()
        {
            InitializeComponent();

        }

        private void Form1_Load_1(object sender, EventArgs e)
        {
            _cOC = new COneCycle("외발 자전거");
            _cC = new CCycle("자전거");
            _cCar = new CCar("자동차");
        }

        private void Dd_Load(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        private void btnOneCycle_Click(object sender, EventArgs e)
        {
            fClearPanel();
            OneCycleDraw();

        }


        // OneCycle 대한 위치 그림을 그려준다.
        private void OneCycleDraw()
        {

            lblName.Text = _cOC.strName;

            Graphics g = pMain.CreateGraphics();

            Pen p = _cOC.fPenInfo();
            g.DrawRectangle(p, _cOC._rtSquare1);
            g.DrawEllipse(p, _cOC._rtCircle1);
        }

        private void fCycleDraw()
        {

            lblName.Text = _cC.strName;

            Graphics g = pMain.CreateGraphics();

            Pen p = _cC.fPenInfo();
            g.DrawRectangle(p, _cC._rtSquare1);
            g.DrawEllipse(p, _cC._rtCircle1);
            g.DrawEllipse(p, _cC._rtCircle2);
        }

        private void fCarDraw()
        {

            lblName.Text = _cCar.strName;

            Graphics g = pMain.CreateGraphics();

            Pen p = _cCar.fPenInfo();
            g.DrawRectangle(p, _cCar._rtSquare1);
            g.DrawRectangle(p, _cCar._rtSquare2);
            g.DrawEllipse(p, _cCar._rtCircle1);
            g.DrawEllipse(p, _cCar._rtCircle2);
        }

        private void btnCycle_Click(object sender, EventArgs e)
        {
            fClearPanel();
            fCycleDraw();
        }


        private void btnCar_Click(object sender, EventArgs e)
        {
            fClearPanel();
            fCarDraw();
        }

        private void fClearPanel()
        {
            pMain.Invalidate();
            Refresh();
        }

        private void btnLeft_Click(object sender, EventArgs e)
        {
            fClearPanel();

            switch (lblName.Text)
            {
                case "외발 자전거":
                    _cOC.fMove(-5);
                    OneCycleDraw();
                    break;
                case "자전거":
                    _cC.fMove(-5);
                    fCycleDraw();
                    break;
                case "자동차":
                    _cCar.fMove(-5);
                    fCarDraw();
                    break;
            }


        }

        private void btnRight_Click(object sender, EventArgs e)
        {
            fClearPanel();
            switch (lblName.Text)
            {
                case "외발 자전거":
                    _cOC.fMove(5);
                    OneCycleDraw();
                    break;
                case "자전거":
                    _cC.fMove(5);
                    fCycleDraw();
                    break;
                case "자동차":
                    _cCar.fMove(5);
                    fCarDraw();
                    break;
            }
          
            
        }
    }
}