2012-01-31 3 views
1

이것은 온라인에서 설명하기가 어려운 어려운 질문이지만 최선을 다할 것입니다. A 형의 변수에 저장되는 B 형의 객체를 인스턴스화했습니다. 이제 get 형 속성을 사용하므로 B 형입니다. 따라서 A 및 B 유형의 암시 적 변환을 수행 했습니까? show()가 B 형인지? B 형의 인스턴스C# 클래스 유형 변환

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

namespace ConsoleApplication1 
{ 

    class A 
    { 
     public virtual void show() 
     { 
      Console.WriteLine("Showing A"); 
     } 

     public void test() 
     { 
      Console.WriteLine("called from A"); 
     } 
    } 

    class B:A 
    { 
     public override void show() 

     { 
      Console.WriteLine("Showing B"); 
     } 

     public void testb() 
     { 
      Console.WriteLine("called from B"); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 


      A a = new B(); 
      // Outputs ConsoleApplication.B 
      Console.WriteLine("{0}", a.GetType()); 
      // outputs showing B 
      a.show(); 
      // outputs called from A 
      a.test(); 

      Console.ReadLine(); 
     } 
    } 
} 
+1

'testb'메소드의 이름을 알고 계십니까? 이것은 오타 일 수 있습니다. – Joe

답변

3

당신은 암시 적 변환을 수행하지 않은 : 당신이 그것에 객체를 다운 캐스트 할 수 있습니다 B 형은 당신에게 예를 들어 형 B.

에 대한 정의를 제공합니다 원래의 유형입니다 무엇이든을 개조했다.

A a = new B(); 

는 직접 B하지만, 두 가지 동작이 독립적으로 고려되어야한다 A의 하위 클래스이므로 입력 A의 변수에서 참조 할 수 유형 B.의 객체를 통해 인스턴스있다.

... = 새 B();

은 왼쪽의 내용에 관계없이 항상 유형 B의 객체를 시작합니다.

A a = ... 

항상 오른쪽에있는 것을 변수 a에 할당하려고합니다.

참조 유형이 다른 점은 CLR에서 개체를 보는 방법뿐입니다.

A a = new B(); 
B b = new B(); 

은 그래서 A 형의 객체 인 것처럼, 'A는'전용)은 (a.show 호출 할 수 있습니다, 당신이 그것으로 작업 할 수 있습니다 그러나 타입 B의 객체와 .test(). 실제로 B 형이기 때문에 testb() 메서드가 추가로 있습니다. 'b'를 사용하면 b.show(), b.test() 및 b.testb()를 호출 할 수 있습니다. 변수 유형에 관계없이 show()를 호출하면 유형이 b이므로 리턴 된 재정의 된 show() 메소드입니다.

마지막으로 지금 할 수있는 것은 다운 캐스트입니다. 즉 B 유형의 객체를 인스턴스화 했으므로 이제이를 b 유형의 변수에 캐스팅 할 수 있으므로 모든 B 유형 구성원에 대한 전체 액세스가 허용됩니다.

예컨대 :

A a = new B(); 
a.testb(); // this will not compile as a does not have a definition of testb(). 

A a = new B(); 
B b = (B)a; // downcast a to a reference of type B 
b.testb(); // this is now fine 

난 그냥 당신에게, 즉 기본 클래스는 A 형과 같은 일을 실체화 할 이유 추가 질문을 보았다. 이것은 서로 다른 유형의 객체로 작업하는 방법으로 공통점을 제공하는 것입니다. 예를 들어 기본 유형의 Animal을 가지고 Cat, Dog, Gerbil과 같은 여러 하위 클래스를 파생시킬 수 있습니다. 그러나 공통 속성으로 작업해야하는 메서드에 모든 Anim 목록을 전달할 수 있기를 원할 수 있습니다. 따라서 Animal에 이름이 있다면 Animal 자체가 Abstract (Instanciated이 가능하지 않음)이고 List는 Dogs, Cats 및 Gerbils만으로 구성 될 수 있음에도 불구하고 List가 반복되고 각 Animals 이름이 참조 될 수 있습니다. 당신은 또한 그 동물과 더 상호 작용할 수있는 유형을 발견함으로써 다양한 동물을 다운 캐스트 할 수 있습니다.

if (animal is Dog) { 
    Dog dog = (Dog)animal; 
} 

아니면 캐스트 수행 할 '로'키워드를 사용할 수 있습니다이 도움이

Dog dog = animal as Dog; 

희망을.

+0

감사합니다. 훌륭한 설명입니다. –

+0

Simon은 (내가 그랬던 것처럼) 정확하지만, A와 B를 함께 사용하여 작업을 수행해야하는 경우, [Liskov Substitution Principle] (http : //en.wikipedia. org/wiki/Liskov_substitution_principle). –

0

변수 a 점, 그래서 변환은 B.show() 방법 a.show() 위해서는 필요하지 않다. 그게 바로 가상 메소드가해야 할 일이다. 선언 된 변수의 유형이 아니라 변수가 참조하는 인스턴스화 된 유형 (또는 상속 체인의 첫 번째 구현)에서 메소드를 호출한다.

a.test()에 대한 호출은 메서드가 virtual이 아니기 때문에 호출하지 않습니다. 따라서 간단히 A.test() 메서드를 호출합니다.

2

변수를 유형 A의 변수에 저장했기 때문에 변수는 여전히 유형 B의 개체를 참조합니다. 변수 "a"를 호출 할 때 CLR은 올바른 호출 방법을 알고 있습니다. show 메소드를 오버라이드 (override)하면 (자), B 형의 show 메소드가 불려갑니다. 하지만 당신은 test()를 오버라이드하지 않았으므로, 타입 A에 대한 메소드 구현이 호출된다. 이는 B가 A에서 test() 동작을 "상속"하지만 B를 무시하지 않았기 때문에 가능합니다. 코드에서

+0

변수는 유형 A이므로이 변수가 유형 B의 객체 참조에 무엇을 제공합니까? B 유형의 변수를 만들면 동일한 작업을 수행 할 수 없습니다. 그리고 만약 그렇다면 왜 타입 A의 가변 변수를 만들고 싶습니까 –

+0

예,'A a = new B()'라는 코드 행을 변경하고 코드를 실행하면 정확히 동일하게 작동합니다 . B 대신에 A를 사용하고자 할 때 많은 장소가 있습니다. 여러분은'public abstract class Shape'을 가지고 있고'public class Circle : Shape'과'public class Square : Shape'을 가집 립시다. Shape 기본 클래스에서 추상 메소드'public abstract void Draw (Graphics g)'를 사용할 수 있습니다. 'List '과'List '을 가지고 다니거나 Circle과 Square에 대한 인스턴스를 포함하는'List '을 가질 수 있습니다. 당신이 보여요? –

1

: show() 가상 방법이기 때문에 "B 표시"

// outputs showing B 
    a.show(); 

인쇄합니다. 모든 가상 메소드 호출은 참조 유형 (런타임에 바인딩)이 아닌 객체 유형에 의해 결정됩니다. 참조 aB 유형의 개체를 가리 킵니다.

// outputs called from A 
    a.test(); 

test()

은 단순히 클래스 A 아닌 가상 메서드에서 상속, 그래서는 "A에서 호출"인쇄합니다. 메서드 호출 a.GetType()은 아무것도 변환하지 않고 단순히 Type 개체의 인스턴스를 반환합니다. 당신이 B 형의 인스턴스를 생성 한 다른 게시물에서 언급 한 바와 같이

0

하지만 최대 캐스트을 입력 할 수있는 객체 당신 때문에 당신이 인터페이스는 A 형에 대한 정의

만약에 정의 된 방법으로 접근 할 필요가 당신이 실제로 가지고있는

if (a is B) 
{ 
    ((B)a).testb(); 
} 

// or 

B b = a as B; 
if (b != null) 
{ 
    b.testb(); 
}