메서드 재정의(virtual, override)


virtual

부모 클래스 함수 앞에 붙는 연산자.

자식 클래스에 의해서 재정의될 수 있다는 의미를 가지고 있다.

컴파일러는 이 지정자가 붙은 함수를 비가상함수와 다르게 컴파일함으로써 재정의될 준비를 한다.


override

자식 클래스 함수 앞에 붙는 연산자.

부모로부터 상속받은 함수와는 다르게 구현한다는 의미를 가지고 있다.

재정의되는 함수는 부모의 함수와 이름, 시그니처도 일치해야함.

재정의된 함수는 부모의 함수에 의존적인 경우가 많은데 이 때 base 키워드로 부모의 원래함수를 호출 할 수 있다.


예제

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

 

class Base

{

    public virtual void echo()

    {

        Console.WriteLine("base echo~!!");

    }

}

 

class Derived : Base

{

    public override void echo()

    {

        Console.WriteLine("derived echo~!!");

    }

}

 

class Program

{

    static void Main()

    {

        Base B = new Base();

        Derived D = new Derived();

        B.echo();

        D.echo();

        Base B2 = D;

        B2.echo();

    }

}

 

실행결과



B.echo와 D.echo는 당연한 결과라고 볼 수 있지만 B2.echo호출문의 결과는

derived echo~!!라는 결과를 출력합니다. 


                                                       Base B2 = D;

위 선언에서 B2의 정적 타입은 Base

B2의 동적 타입은 Derived가 됩니다.


일반적인 비가상 메서드는 정적 타입을 따르지만 가상 메서드에서는 

호출 객체가 실제로 가리키고 있는 타입, 즉 동적 타입을 따르게 됩니다.


echo함수가 가상함수 일 때에는 B2가 비록 Base타입이지만 Derived객체를 가리키고 있기 때문에

Derived의 메서드가 호출이 됩니다.


그렇다면 위 예제를 비가상 함수로 바꾸어 출력을 해보도록 하겠습니다.


public virtual void echo()

이 부분에서 virtual을 빼고,

public override void echo()

이 부분에서 override는 new로 바꾸어 출력해보겠습니다.



실행결과




참고.

여기서 new를 안붙이고 public void echo()로 변환해도 결과는 같습니다.

new를 붙이는 이유는 상속받은 멤버를 완전히 숨겨버리고 자식 클래스가 같은 이름으로 새로운 멤버를 만든다는 뜻으로써, 의도적으로 같은 이름을 사용한다는 것을 알리는 연산자라고 볼 수 있습니다.

물론 멤버를 숨기는 것이지 상속을 안받는다는 뜻은 아닙니다.

base.메서드명()을 이용하면 부모의 숨겨진 멤버를 상속 받을 수 있게 됩니다.

신고

'Windows Programming > Windows::C#' 카테고리의 다른 글

[C#] 메서드 재정의(virtual, override)  (0) 2013.03.31
[C#] 상속 예제  (0) 2013.03.31
C# GUI 구구단 프로그램  (0) 2012.02.16
윈도우즈 폼 예제  (0) 2012.02.16
C# 콘솔 예제(성적관리 프로그램)  (0) 2012.02.16

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

 

class Human

{

    protected string Name;

    protected int Age;

    public Human(string aName, int aAge)

    {

        Name = aName;

        Age = aAge;

    }

    public virtual void Intro()

    {

        Console.WriteLine("Name : " + Name);

        Console.WriteLine("Age : " + Age);

    }

}

 

class Student : Human

{

    protected int StNum;

    public Student(string aName, int aAge, int aStNum) : base(aName, aAge)

    {

        StNum = aStNum;

    }

    public override void Intro()

    {

        base.Intro();

        Console.WriteLine("stuNumber : " + StNum);

    }

    public void Study()

    {

        Console.WriteLine("study");

    }

}

 

class Program

{

    static void Main()

    {

        Student Kim;

        Kim = new Student("Minhwa Jin", 25, 921223);

        Kim.Intro();

        Kim.Study();

    }

}

 

base(aName, aAge)

부모의 생성자를 호출하여 초기화하는 구문입니다.

기존의 StNum은 직접 자신의 생성자에서 초기화를 하게 되구요.


여기서 base를 주석처리를 하게 되면 기반 클래스(부모)의 디폴트 생성자가 호출되는데요.

Human에서는 디폴트 생성자가 없기 때문에 에러가 납니다.


이름과 나이를 출력하는 코드가 기반 클래스(부모)에 작성되어있기 때문에

Intro를 호출하면 출력이 되겠지요~


그리고 기본적으로 c#상속은 public 상속만 지원하며, 다중 상속을 지원하지 않고

상속없이 단독 클래스를 정의하는 것도 허용되지 않는다고 합니다~


실행결과





아 참고로 제나이 22 입니다...-_-;


신고

'Windows Programming > Windows::C#' 카테고리의 다른 글

[C#] 메서드 재정의(virtual, override)  (0) 2013.03.31
[C#] 상속 예제  (0) 2013.03.31
C# GUI 구구단 프로그램  (0) 2012.02.16
윈도우즈 폼 예제  (0) 2012.02.16
C# 콘솔 예제(성적관리 프로그램)  (0) 2012.02.16



// form1.cs 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// textBox1의 Text를 읽어서 gugudan함수를 호출하여 구구단을 출력시키는 프로그램이다.
namespace gugudan
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e) // 버튼1을 클릭했을 때 이벤트발생
        {
            gugudan(int.Parse(textBox1.Text)); //구구단 함수 출력함수호출, 그리고 받아들이는 textBox1.Text는 string형이므로 int형으로 형변환을 해야한다.
        }
        private void gugudan(int number)
        {
            textBox1.Text = "";
            label1.Text = "";
            for (int i = 2; i <= 9; i++) // for문 이용하여 *2~*9까지 출력
            label1.Text += number.ToString() + " * " + i.ToString() + " = " + (number *               i).ToString() + "\n"; 
// 출력하는 방식은 간단히 문자열을 더한다고 생각하면 편하겠다. 그리고 label1.Text는 마찬가지로 string형이기 때문에 ToString()이라는 메서드를 이용하여 문자열로 다시 바꾸어서 저장시킨다.
            }
        }

        private void button2_Click(object sender, EventArgs e) // 버튼2(초기화)
        {
            label1.Text = "";  // 구구단이 출력된 것을 지워준다,초기화
        }
    }
}

12를 입력하고 출력버튼을 눌렀을 경우 오른쪽 화면에서와 같이 구구단이 출력된다....
신고

'Windows Programming > Windows::C#' 카테고리의 다른 글

[C#] 메서드 재정의(virtual, override)  (0) 2013.03.31
[C#] 상속 예제  (0) 2013.03.31
C# GUI 구구단 프로그램  (0) 2012.02.16
윈도우즈 폼 예제  (0) 2012.02.16
C# 콘솔 예제(성적관리 프로그램)  (0) 2012.02.16
사실 c#의 가장 큰 장점이라고 할 수 있는 부분은 바로, 문자 기반의 칙칙한 콘솔에 비해서 그래픽을 사용할 수 있고 컨트롤을 활용할 수 있어 훨씬 더 섬세한 표현이 가능하다. 
그렇다면 간단히 버튼과 라벨을 이용한 쉬운 GUI 프로그램 예제를 만들어보자.
일단 Visual Studio를 실행시키고 새 프로젝트에서 화면에서와같이 Windows Forms 응용 프로그램을 선택하고 이름을 WindowsForm이라는 프로젝트 하나를 만들어보자. 



확인버튼을 누르게되면 이렇게 나올 것이다.


위에서와 같이 빈 폼이 하나 뜰 것이고 도구상자와 속성을 이용하여 이제 여러가지 버튼이나 이벤트, 설정 등을 할 수 있다. 그렇다면 도구상자를 이용하여 라벨하나와 버튼 두개를 만들어 보자.


이렇게 간단히 도구상자를 이용하여 라벨 하나와 버튼 두개를 드래그를 이용하여 폼에다가 만들어봅시다!!

이제 만드려는 프로그램은 button1을 누를경우 label1텍스트가 button1 로 바뀌고, 또 button2를 누를경우 button2로 바뀌는 이벤트를 만들어 볼 것이다. 
먼저 button1을 더블클릭 해보자
그렇게되면 밑에서와같이 코드 창이 나올것이다.

 
button1을 클릭했을 경우 이벤트를 설정하는 함수가 나올 것이다. 이제 이 함수 괄호 안에다가 적는 제어문이 프로그램을 실행시켰을 경우 버튼을 클릭했을 때 실행되는 것이다. 그러면 이 괄호 안에 label1의 텍스를 바꿔야 하기 때문에 이렇게 제어문을 입력시켜보자.

 
button2 클릭 이벤트까지 완성 

자그러면 컴파일을 한 후 프로그램을 실행시켜보자....

 

(프로그램 실행 초기,            버튼1을 눌렀을 때,             버튼2를 눌렀을 때           )

위와같이 도구상자를 이용하여 간단히 이벤트에 대한 제어문만 작성해주면 간단히 GUI 프로그램을 만들 수 있다.

신고

'Windows Programming > Windows::C#' 카테고리의 다른 글

[C#] 메서드 재정의(virtual, override)  (0) 2013.03.31
[C#] 상속 예제  (0) 2013.03.31
C# GUI 구구단 프로그램  (0) 2012.02.16
윈도우즈 폼 예제  (0) 2012.02.16
C# 콘솔 예제(성적관리 프로그램)  (0) 2012.02.16
using System;

class Program
{
    static public void Menu()
    {    //메뉴 출력루틴
        Console.WriteLine("************성적 관리 프로그램***********");
        Console.WriteLine("*******     1.학생 정보 입력      *******");
        Console.WriteLine("*******     2.학생 성적 입력      *******");
        Console.WriteLine("*******     3.학생 성적 계산      *******");
        Console.WriteLine("*******     4.학생 정보 출력      *******");
        Console.WriteLine("*******     5.학생 성적 출력      *******");
        Console.WriteLine("*******     6.종료                *******");
        Console.WriteLine("*****************************************");
    }
    static public void sort(Student[] stu)
    {
        for (int k = 0; k < Student.count; k++)
        {
            if (stu[k].number != 0)
            {
                stu[k].Grade.aver = stu[k].Grade.english +
                      stu[k].Grade.korean + stu[k].Grade.math;
                stu[k].Grade.aver /= (double)3; //언수외 3과목 평균
            }
        } //학생의 평균 계산

        for (int k = 0; k < Student.count; k++)
        {
            for (int j = 0; j < 20 - (k + 1); j++)
                //이미 가장 오른쪽 정렬이 되어있기 때문에 length-(i+1)까지
                if (stu[j].Grade.aver < stu[j + 1].Grade.aver)
                    swap(stu[j], stu[j + 1]);
        } //학생 언수외 평균성적으로 정렬. 거품(버블)정렬

        for (int p = 0; p < Student.count - 1; p++)
        {
            stu[p].number = p + 1;
        } //언수외 성적순으로 학생의 번호도 다시 새로 정렬
    }

    static public void swap(Student stu1, Student stu2)
    {    //성적순으로 sorting 하는 과정에서 사용하는 함수
        Student temp = new Student();
        temp.Insert(stu1);
        stu1.Insert(stu2);
        stu2.Insert(temp);
        //tmp를 이용하여 swap.
    }
    static void Main(string[] args)
    {
        int menu;
        int i;
        Student[] stu;
        stu = new Student[20]; //최대 20개의 객체 생성
        for (i = 0; i < 20; i++)
            stu[i] = new Student();
        bool[] check_gr = new bool[20]; // grade 확인 배열

        while (true)
        {
            i = 0;
            Menu(); // 프로그램이 한번 회전할 때, 메뉴 출력
            Console.Write("메뉴를 입력하세요 : ");
            menu = Convert.ToInt32(Console.ReadLine()); //메뉴 입력
            switch (menu) //메뉴에 따른 case 실행
            {
                case 1:
                    if (Student.count == 21)
                    {    //학생수 최대 20명 생성가능
                        Console.Write("학생수가 20명을 넘었습니다.");
                        continue;
                    }
                    stu[Student.count - 1].Setinfo(); //학생 정보 입력
                    break;
                case 2:
                    Console.Write("학생의 번호를 입력하세요 1~20: ");
                    i = Convert.ToInt32(Console.ReadLine());
                    if (i > Student.count - 1)
                    {
                        Console.WriteLine(i + "번 학생이 존재하지 않습니다.");
                    } //학생 정보가 존재하는 데이터에만 정보 입력 가능
                    else
                    {
                        stu[i - 1].Grade.SetGrade(stu[i - 1]);
                    } //학생 성적 입력
                    check_gr[Student.count] = true;
                    break;
                case 3:
                    sort(stu); // 정렬함수
                    break;
                case 4:
                    Console.WriteLine("************************");
                    Console.WriteLine("n 학번\t이름\t나이\t주소\t성별");
                    Console.WriteLine("************************");
                    for (int k = 0; k < 20; k++)
                    {
                        if (stu[k].number != 0)
                        {
                            Console.Write(stu[k].number + " ");
                            stu[k].Getinfo();
                        }
                    } // 학생의 정보 출력
                    break;
                case 5:
                    Console.WriteLine("************************");
                    Console.WriteLine("n 학번\t이름\t국어\t영어\t수학\t평균");
                    Console.WriteLine("************************");
                    for (int k = 0; k < Student.count; k++)
                    {
                        if (stu[k].number != 0)
                        {
                            Console.Write(stu[k].number + " ");
                            stu[k].Grade.GetGrade();
                        }
                    } //학생의 성적정보 출력

                    break;
                case 6:
                    Console.WriteLine("수고하셨습니다.");
                    return;
                default:
                    continue;
            }
        }
    }
}


class Student
{
    public static int count = 1;
    public int number;
    public grade Grade; //성적 객체를 포함한다.
    public string Id;
    public string Name;
    public string Age;
    public string Address;
    public string Sex; //student객체의 변수들

    public Student(Student input)
    {
        //number = input.number;
        Id = input.Id;
        Name = input.Name;
        Age = input.Age;
        Address = input.Address;
        Sex = input.Sex;

        Grade.Id = input.Grade.Id;
        Grade.Name = input.Grade.Name;
        Grade.korean = input.Grade.korean;
        Grade.math = input.Grade.math;
        Grade.english = input.Grade.english;
        Grade.aver = input.Grade.aver;
        Grade = new grade(this); //생성과 동시에 객체 생성
    } //생성자를 오버로딩하여 2개의 경우를 두었다.
    //위 경우는 생성과 동시에 객체를 삽입하는경우.

    public Student()
    {
        Grade = new grade(this); //생성과 동시에 객체 생성
    } //생성자 함수에 오버로딩 사용
    //생성과 동시에 Setinfo()함수를 메인에서 불러주므로
    //따로 초기화하지 않음.

    public void Insert(Student input)
    {
        number = input.number;
        Id = input.Id;
        Name = input.Name;
        Age = input.Age;
        Address = input.Address;
        Sex = input.Sex;

        Grade.Id = input.Grade.Id;
        Grade.Name = input.Grade.Name;
        Grade.korean = input.Grade.korean;
        Grade.math = input.Grade.math;
        Grade.english = input.Grade.english;
        Grade.aver = input.Grade.aver;
    } //객체 복사함수. swap에 사용된다.

    public void Setinfo()
    {
        Console.Write("학번 : ");
        Id = Console.ReadLine();
        Grade.Id = Id;
        Console.Write("이름 : ");
        Name = Console.ReadLine();
        Grade.Name = Name;
        Console.Write("주소 : ");
        Address = Console.ReadLine();
        Console.Write("나이 : ");
        Age = Console.ReadLine();
        Console.Write("성별 : ");
        Sex = Console.ReadLine();
        number = Student.count;
        Student.count++;
    } //학생의 정보를 입력한다.

    public void Getinfo()
    {
        Console.Write(Id + "\t");
        Console.Write(Name + "\t");
        Console.Write(Address + "\t");
        Console.Write(Age + "\t");
        Console.WriteLine(Sex);
    } //학생 정보를 출력한다.
}
class grade
{
    public string Name;
    public string Id;
    public int korean;
    public int english;
    public int math;
    public double aver;

    public grade(Student stu)
    {
        Name = stu.Name;
        Id = stu.Id;
        korean = 0;
        english = 0;
        math = 0;
        aver = 0;
    } //생성과 동시에 변수 초기화
    public void SetGrade(Student stu)
    {
        Console.Write("국어 : ");
        korean = int.Parse(Console.ReadLine());

        Console.Write("영어 : ");
        english = int.Parse(Console.ReadLine());

        Console.Write("수학 : ");
        math = int.Parse(Console.ReadLine());
        Name = stu.Name;
        Id = stu.Id;
    } //학생의 성적 정보를 삽입하는 함수.

    public void GetGrade()
    {

        Console.Write(Name + "\t");
        Console.Write(Id + "\t");
        Console.Write(korean + "\t");
        Console.Write(english + "\t");
        Console.Write(math + "\t");
        Console.WriteLine(aver);
    } //학생의 성적을 얻어오는 함수

}

신고

'Windows Programming > Windows::C#' 카테고리의 다른 글

[C#] 메서드 재정의(virtual, override)  (0) 2013.03.31
[C#] 상속 예제  (0) 2013.03.31
C# GUI 구구단 프로그램  (0) 2012.02.16
윈도우즈 폼 예제  (0) 2012.02.16
C# 콘솔 예제(성적관리 프로그램)  (0) 2012.02.16

+ Recent posts

티스토리 툴바