2016-05-31 5 views
0
public class BaseClass 
    { 
     public virtual void Display() 
     { 
      Console.WriteLine("I am Base Class"); 
     } 

     public void BaseClassMethod() 
     { 
      Console.WriteLine("I am Base Class Method"); 
     } 
    } 

    public class DerivedClass : BaseClass 
    { 
     public override void Display() 
     { 
      Console.WriteLine("I am Derived Class"); 
     } 

     public void DerivedClassMethod() 
     { 
      Console.WriteLine("I am Derived Class Method"); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      BaseClass bc = new BaseClass(); 
      bc.Display(); 
      bc.BaseClassMethod(); 

      Console.WriteLine("--------------"); 

      DerivedClass dc = new DerivedClass(); 
      dc.Display(); 
      dc.BaseClassMethod(); 
      dc.DerivedClassMethod(); 

      Console.WriteLine("--------------"); 

      BaseClass bc2 = new DerivedClass(); 
      bc2.Display(); 
      bc2.BaseClassMethod(); 
      //bc2.DerivedClass(); --> I can't reach b2.DerivedClass() method 

      Console.ReadLine(); 
     } 
    } 

모두 안녕하세요. 나는 왜 그리고 왜 내가 기본 클래스 참조에서 파생 클래스 객체를 만들고 사용하고자하는지에 대해 내 마음을 깨끗이하려고 노력하고있다. 나는 가상이 어떻게 작동 하는지를 안다. 파생 클래스가 기본 클래스이며 가상 메서드를 재정의 할 수 있음을 알고 있습니다. 나는 기본 클래스에서 비 가상 메소드에 접근 할 수있다. 그러나 나는 왜이 스타일의 객체 생성을 사용할 수 있는지 그리고 왜 그럴 수 있는지 알고 싶습니다. 예제 코드의 마지막 부분 에서처럼;기본 클래스 참조로 객체를 생성해야하는 이유는 무엇입니까?

BaseClass bc2 = new DerivedClass(); 

파생 클래스 메서드를 사용할 수 없어 파생 클래스 메서드를 사용할 수 없습니다. 그러나 새로운 DerivedClass 때문에 여전히 파생 클래스입니다. 정상적인 DerivedClass를 사용한다면 d = new DerivedClass(); 스타일, 나는 두 클래스 방법을 모두 사용할 수 있습니다. 나는이 스타일을 사용하고자하는 이유와 상황을 찾을 수 없다. 누구든지 나를 보여 주면 기쁠 것입니다.이 스타일이 언어로 존재한다는 것을 이해할 수 있도록 기본 클래스 참조에서 파생 클래스 객체를 사용해야하는 상황입니다. 나는 왜 이것이 작동하지 않는지 또는 그런 식으로 물어 보는 것이 아니라는 것을 알고 싶습니다. 상황을 알고 싶습니다. 고맙습니다.

내가 원, 사각형, 및 보유 할 수있는 목록을 가지고 조금 귀하의 예를

public class Shape 
{ 
    public virtual void Display() 
    { 
     Console.WriteLine("I am a Shape"); 
    } 

    public void BaseClassMethod() 
    { 
     Console.WriteLine("I am Base Class Method"); 
    } 
} 

public class Square : Shape 
{ 
    public override void Display() 
    { 
     Console.WriteLine("I am Square"); 
    } 

    public void DerivedClassMethod() 
    { 
     Console.WriteLine("I am Derived Class Method"); 
    } 
} 



public class Circle : Shape 
{ 
    public override void Display() 
    { 
     Console.WriteLine("I am Circle"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Shape> shapes = new List<Shape(); 
     shapes.Add(new Square()); 
     shapes.Add(new Circle()); 

을 변경할 수 있습니다 여러 유형의

1) 컬렉션 :

+0

'클래스 상속'에 대한 읽기/연구를 수행하셨습니까? 아마도 당신은'OOP'에서'C# MSDN 구글 검색'을 할 수있을 것입니다. 누가 어떻게, 왜, 어떻게 그리고 왜 – MethodMan

+0

, 여러분이 오직 하나의 기본 클래스와 그것으로부터 파생 된 클래스 하나를 가질 때, 당신은 가지 않을 것입니다. 많은 가치를 찾는다. 공통된 기능을 가진 여러 클래스가 있지만 상속의 이점을 얻을 수있는 구현 경로가 다를 때입니다. – Jonesopolis

+0

요약 : 기본 클래스 기능 세트가 제공해야하는 것보다 더 많은 용도로 사용되지 않을 것이라고 독자에게 알립니다. 파생 된 타입을 선언하는 것은 "논리적 잡음"입니다. 그것은 필요한 것 이상으로 복잡한 것을 만들지 않는 것입니다. 작업에 적합한 도구를 사용하십시오. –

답변

2

는 두 가지 용도가있다 일반 도형은 모두 단일 컬렉션에 있습니다.

2) 다형성

우리는, 그러나 우리는 그것이 어떤 종류가있을 것이라는 점을 알고있다 Shape 변수 shape의 종류를 모르는 이전 코드

  foreach(Shape shape in shapes) 
     { 
      shape.Display(); 
     } 

에서에 계속 Display() 메서드를 호출하면 올바른 정보가 표시됩니다.

다형성은 뭔가에 함수를 호출해야하지만 위와 같은 기본 유형 모음을 가져 오거나 특정 유형을 알 수없는 경우 유용 할 수있는 함수를 작성하려는 경우 유용합니다. 어떤 종류의 Shape을 가져 가라. 왜냐하면 그 기능이 그 일을하기 위해 특정한 종류를 알 필요가 없기 때문이다.

public static void LogDisplay(Shape shape) 
    { 
     Console.WriteLine("I am about to call shape.Display()"); 
     shape.Display(); 
     Console.WriteLine("I am just called shape.Display()"); 
    } 
+0

답변 해 주셔서 감사합니다. 다른 유익한 해답이 있지만 첫 번째 것이기 때문에 나는 너를 받아 들인다. 그래서 사각형이나 원을 shape.Add (새 사각형()); , List 내에서 기본 클래스 참조를 사용하여이 객체를 만듭니다. – alpersilistre

+1

나는 당신의 질문을 잘 이해하고 있지는 않지만 그 대답은 "예"라고 생각합니다. –

2

사람들이 사용법을 이해할 수 있기 때문에 내가 좋아하는 예가 기록됩니다. 웹 사이트를 만들었다 고 상상해보십시오. 사이트를 개발할 때 액세스가 쉽기 때문에 파일 시스템에 로그인하고 싶습니다. 웹 사이트를 배포 할 때 해당 컴퓨터의 파일 시스템에 직접 액세스 할 수 없기 때문에 이벤트 로그에 기록하려고합니다.

그러나 상황이 로깅되는 위치 만 변경하려고합니다. 기본 클래스가 실제 텍스트가 어떻게 보이는지 구조화하기를 원합니다.

public class FileLogger : BaseLogger 
{ 
    public FileLogger(string filename) 
    { 
     //initialize the file, etc 
    } 

    public override void LogException(Exception ex) 
    { 
     var string = GetStringFromException(ex); 
     File.WriteAllLines(...); 
    } 

    public override void LogException(Exception ex) 
    { 
     var string = GetStringFromUserMessage(ex); 
     File.WriteAllLines(...); 
    } 
} 

및 이벤트 로그에 기록 내 수업 :

public abstract class BaseLogger 
{ 
    public abstract void LogException(Exception ex); 
    public abstract void LogUserMessage(string userMessage); 

    protected string GetStringFromException(Exception ex) 
    { 
     //.... 
    } 

    protected string GetStringFromUserMessage(string userMessage) 
    { 
     //.... 
    } 
} 

가 지금은 파일 시스템에 로그 클래스를 가질 수 있습니다 그래서 텍스트 포맷 내 기본 클래스를 가지고

public class EventLogger : BaseLogger 
{ 
    public EventLogger() 
    { 
     //initialize the eventlog, etc 
    } 

    public override void LogException(Exception ex) 
    { 
     var string = GetStringFromException(ex); 
     EventLog.WriteEntry(...); 
    } 

    public override void LogException(Exception ex) 
    { 
     var string = GetStringFromUserMessage(ex); 
     EventLog.WriteEntry(...); 
    } 
} 

이제 내 프로그램에서, 나는 내 수업에 하나를 주입 할 때 BaseLogger이 있다고 신경 쓴다. 구현 세부 사항은 부적절합니다. 단지 내가 사용하고있는 것과 상관없이 LogExceptionLogUserMessage을 사용할 수 있음을 알고 있습니다.

내가 내가를 사용하는 클래스를 파생 배려하지에서 로거 I 혜택을 사용하여 야합니다. 파생 클래스를 기본 클래스처럼 취급하면 이점이 있습니다. 나는 프로그램을 돌보지 않고 그들을 바꿀 수있다.

0

파생 클래스를 사용할 수 있는지에 대한 추론은 반복 코드를 최소화하는 것과 관련이 있습니다.

실생활의 예를 참조하십시오 ... 저는 자동차의 속성과 능력을 설명하라고 한 다음 전기 자동차에 대해서도 똑같이하도록 요청한 경우, 속성과 능력의 두 가지가 공유됩니다. 따라서 완전히 별도의 두 클래스가되는 대신 기본 클래스 Car를 만들고이를 통해 electricCar를 유도하는 것이 더 효율적입니다. 그런 다음 파생 된 클래스 내에서 전기 자동차의 구체적인 차이점 만 설명하면 공유 된 모든 특성과 기능이 이어집니다.

희망 사항은 기본 클래스와 파생 클래스의 유용성을 이해하는 데 도움이됩니다. 매우 간단하지만 개념을 이해하는 데 도움이 될 것 같아요!

1

코드 재사용 성 및 확장성에 주로 많은 이유가 있습니다. 다시 말하면, 전체적으로 많이 재 작성 할 필요없이 쉽게 작은 변경이나 기능 향상을 할 수 있습니다.

다른 데이터베이스 (또는 다른 테이블 구조)를 지원해야하는 고객이 소프트웨어를 사용하는 고객이 다른 경우가 종종 있습니다. 따라서이를 수행하기 위해 공통 기본 클래스에서 구현을 파생시킬 수 있으며 나머지 프로그램에는 영향을 미치지 않으면 서 구현 세부 사항을 변경할 수 있습니다.

이것은 또한 그런 다음 메인 프로그램에서 당신이 할 수있는

public abstract class ProviderBase 
{ 
    public abstract Employee[] GetAllEmployees(); 
} 

public class MySqlProvider:ProviderBase 
{ 
    public override Employee[] GetAllEmployees() 
    { 
     string select = "select * from employees"; 

     //query from mysql ... 
    } 

} 

public class MsSqlProvider : ProviderBase 
{ 
    public override Employee[] GetAllEmployees() 
    { 
     string select = "select * from user u left join employee_record e on u.id=e.id"; 

     //query from mysql ... 
    } 
} 

에 설명되어있다 "는 '인터페이스'가 아닌 '구현'에 프로그램 "설계 원칙을 다음과 구성 또는 Dependency Injection

ProviderBase provider = null; 
if(databaseType == "MySql") 
{ 
    provider = new MySqlProvider(); 
} 
else if (databaseType == "MsSql") 
{ 
    provider = new MsSqlProvider(); 
} 

var employees = provider.GetAllEmployees(); 
//do something 
0

에 의해를 사용하는 주된 이유를 데이터베이스 구현의 유형을 변경할 수 기본 클래스는 재사용다형성이다

그래서 당신은 조건에 따라 클래스를 만들 수 있습니다 : 당신이 어떤 종류의 모르더라도 당신이 bc를 사용할 수있는 다음과 같은 응용 프로그램에서

BaseClass bc 
if(case1) 
    bc = new DerivedClass1(); 
else 
    bc = new DerivedClass2(); 

을 컴파일 타임에 파생 클래스입니다. 예를 들어 전달할 수 있습니다. 파생 클래스 메서드는 실제 파생 클래스의 종류를 아는 경우에만 사용할 수 있습니다. 예를 들면 다음과 같습니다. 그런 다음 전환을 수행 할 수 있습니다.

DerivedClass1 dc = bc as DerivedClass1; 
dc.DerivedClassMethod() 
관련 문제