Скрытие методов, присутствующих в базовом классе
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, владелец);
присутствующий в классе Locksmith (внутри метода OpenSafe()), вызовет метод ReturnContents () для представления объекта Jewelthief, если ссылается на объект 'JewelThief'.
Но каждый раз, когда он вызывает метод базового класса, ReturnContents. Как это поведение объясняется?
2 ответа
В C# вы должны объявить свои виртуальные методы. Может быть, вы думаете о JAVA?
Измените подписи вашего метода на:
public virtual void ReturnContents(Jewels safeContents, Owner owner)
для базового класса и:
public override void ReturnContents(Jewels safeContents, Owner owner)
для детского класса.
Скрытие происходит, когда дочерний класс переопределяет метод, который базовый класс уже определил. В этом случае среда выполнения вызовет метод ссылочного типа и не будет использовать полиморфизм. Если это необходимо, вы должны пометить метод в подклассе ключевым словом "new". Однако если вы хотите использовать полиморфизм, вам нужно объявить метод базового класса как виртуальный и использовать ключевое слово "override" для метода в дочернем классе.
Вы бы использовали скрытие в том случае, если вы хотите использовать большую часть кода в базовом классе, но вы хотите иметь новое поведение в своем классе для определенного метода и предоставлять его всем подклассам того, для которого вы определяете использовать сокрытие. Это не позволит изменить поведение базового класса для его внутренних вызовов метода, но все же позволит вам предложить новую реализацию пользователям вашего нового класса.
Если вы не хотите Override
метод, который вы можете скрыть с помощью new
оператор
public new void ReturnContents(Jewels safeContents, Owner owner)
{
stolenJewels = safeContents;
Console.WriteLine("JewelThief:I'm stealing the contents! " + stolenJewels.Sparkle());
}