2013-03-04 2 views
2
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace LearnOverride 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Owner owner = new Owner(); 
      Safe safe = new Safe(); 

      Console.WriteLine("When \tLocksmith locksmith = new Locksmith();\n"); 
      Locksmith locksmith = new Locksmith(); 
      locksmith.OpenSafe(safe, owner); 
      Console.WriteLine("when ReturnContents() called from main,"); 
      Jewels openedLocksmith = safe.Open("12345"); 
      locksmith.ReturnContents(openedLocksmith, owner); 
      Console.WriteLine(); 

      Console.WriteLine("\n\nWhen \tJewelThief jewelThief = new JewelThief();\n"); 
      JewelThief jewelThief = new JewelThief(); 
      jewelThief.OpenSafe(safe, owner); 
      Console.WriteLine("when ReturnContents() called from main,"); 
      Jewels opened = safe.Open("12345"); 
      jewelThief.ReturnContents(opened, owner); 
      Console.WriteLine(); 

      Console.WriteLine("\n\nWhen \tLocksmith jewelThiefAsLocksmith = new JewelThief();\n"); 
      Locksmith jewelThiefAsLocksmith = new JewelThief(); 
      jewelThiefAsLocksmith.OpenSafe(safe, owner); 
      Console.WriteLine("when ReturnContents() called from main,"); 
      Jewels j = safe.Open("12345"); 
      jewelThiefAsLocksmith.ReturnContents(j, owner); 

      ///JewelThief jewelThief = new Locksmith(); is error 
      Console.ReadKey(); 
     } 
    } 

    class Jewels 
    { 
     public string Sparkle() 
     { 
      return "Sparkle, sparkle!"; 
     } 
    } 

    class Safe 
    { 
     private Jewels contents = new Jewels(); 
     private string safeCombination = "12345"; 
     public Jewels Open(string combination) 
     { 
      if (combination == safeCombination) 
       return contents; 
      else 
       return null; 
     } 
     public void PickLock(Locksmith lockpicker) 
     { 
      lockpicker.WriteDownCombination(safeCombination); 
     } 
    } 

    class Owner 
    { 
     private Jewels returnedContents; 
     public void ReceiveContents(Jewels safeContents) 
     { 
      returnedContents = safeContents; 
      Console.WriteLine("Owner:Thank you for returning my jewels! " + safeContents.Sparkle()); 
     } 
    } 

    class Locksmith 
    { 
     public void OpenSafe(Safe safe, Owner owner) 
     { 
      safe.PickLock(this); 
      Jewels safeContents = safe.Open(writtenDownCombination); 
      this.ReturnContents(safeContents, owner); 
     } 

     private string writtenDownCombination = null; 
     public void WriteDownCombination(string combination) 
     { 
      writtenDownCombination = combination; 
     } 
     public void ReturnContents(Jewels safeContents, Owner owner) 
     { 
      owner.ReceiveContents(safeContents); 
     } 
    } 

    class JewelThief : Locksmith 
    { 
     private Jewels stolenJewels = null; 
     public void ReturnContents(Jewels safeContents, Owner owner) 
     { 
      stolenJewels = safeContents; 
      Console.WriteLine("JewelThief:I'm stealing the contents! " + stolenJewels.Sparkle()); 
     } 
    } 
} 

위 코드는 메서드 ReturnContents()를 재정의하지 않습니다. 그것은 숨어 있습니다. 그래서 나는 기대하고 있었다 성명기본 클래스에있는 메서드 숨기기

this.ReturnContents (safeContents, owner);

(OpenSafe() 메소드 내부에 있음), 객체 'JewelThief'에서 참조하는 경우 ReturnContents() 메소드가 현재 Jewelthief 객체를 호출합니다.

하지만 항상 기본 클래스 메소드 인 ReturnContents를 호출합니다. 이 행동은 어떻게 설명됩니까?

+0

있는지 아니 new 연산자를 사용하여 당신이 그것을 숨길 수있는 방법을 Override 싶지 않다합니다. – TalentTuner

+0

'virtual-override'를 사용할 수 있다는 것을 알고 있습니다. 그러나 방법을 숨길 때 그 행동을 배우고있었습니다. – SHRI

+0

이 또한 숨어 있지 않습니다. 재정의 된 메서드에 새 키워드를 사용해야합니다. – TalentTuner

답변

4

C#에서는 가상 메서드를 선언해야합니다. 어쩌면 당신은 자바에 대해 생각하고 있습니까? 기본 클래스에 대한

public virtual void ReturnContents(Jewels safeContents, Owner owner) 

및 :

은 당신의 방법 서명을 변경

public override void ReturnContents(Jewels safeContents, Owner owner) 

을 하위 클래스.

자식 클래스가 기본 클래스가 이미 정의한 메서드를 다시 정의하면 숨김이 발생합니다. 이 경우 런타임은 참조 된 유형의 메소드를 호출하고 다형성을 사용하지 않습니다. 이 동작이 필요한 경우 하위 클래스의 메서드를 "new"키워드로 표시해야합니다. 그러나 다형성을 사용하려면 기본 클래스의 메서드를 가상으로 선언하고 자식 클래스의 메서드에 "override"키워드를 사용해야합니다.

기본 클래스에서 대부분의 코드를 사용하려는 경우 숨기기를 사용하지만 특정 메서드에 대해 클래스에서 새로운 동작을 사용하고이 코드를 모든 하위 클래스에 표시하려는 경우 숨기기를 사용하도록 정의하고 있습니다. 이렇게하면 메소드에 대한 내부 호출을위한 기본 클래스의 동작을 변경하지 않지만 새 클래스의 사용자에게 새 구현을 제공 할 수 있습니다.

+0

예, 저는 방법을 숨기는 동작에 대해 연구하고있었습니다. 무시하지 말고. – SHRI

+1

@SHRI를 무시하지 않고'Locksmith' 변수에서'JewelThief' 메소드를 호출 할 수 없습니다. –

+0

@SHRI 내 업데이트를 참조하십시오. –

0

당신은 당신이 코드에서 일을하지만 ReturnContents은 자물쇠 클래스에서 가상으로 표시되지 않을 것입니다 무슨

public new void ReturnContents(Jewels safeContents, Owner owner) 
    { 
     stolenJewels = safeContents; 
     Console.WriteLine("JewelThief:I'm stealing the contents! " + stolenJewels.Sparkle()); 
    } 
+0

동의합니다. '새'키워드를 사용해야했습니다. 차이점을 알고 싶을 때 : this.ReturnContents() 및 jewelThief.ReturnContents() – SHRI

관련 문제