using System;

namespace OverridingAnInterfaceImplementation
{
	interface IStorable
	{
		void Read();
		void Write();
	}

	public class Note : IStorable
	{
		public Note(string s)
		{
			Console.WriteLine(
			"Tworzenie obiektu klasy Note: {0}", s);
		}

		// Uwaga – metoda wirtualna
		public virtual void Read()
		{
			Console.WriteLine(
			"Metoda Read interfejsu IStorable w klasie Note");
		}

		// Uwaga — ta metoda nie jest wirtualna!
		public void Write()
		{
			Console.WriteLine(
			"Metoda Write interfejsu IStorable w klasie Note");
		}
	}

	public class Document : Note
	{
		public Document(string s)
			:
		   base(s)
		{
			Console.WriteLine(
			   "Tworzenie obiektu klasy Document: {0}", s);
		}

		// Przesłanianie metody Read 
		public override void Read()
		{
			Console.WriteLine(
			   "Przesłanianie metody Read w klasie Document!");
		}

		// Implementacja własnej metody Write
		public new void Write()
		{
			Console.WriteLine(
			   "Metoda Write w klasie Document!");
		}
	}

	class Tester
	{
		public void Run()
		{
			Note theNote = new Document("Dokument testowy");

			theNote.Read();
			theNote.Write();

			Console.WriteLine("\n");

			IStorable isStorable = theNote as IStorable;
			if (isStorable != null)
			{
				isStorable.Read();
				isStorable.Write();
			}
			Console.WriteLine("\n");

			// Tym razem program tworzy zmienną typu pochodnego
			Document theDoc = new Document("Drugi test");

			theDoc.Read();
			theDoc.Write();
			Console.WriteLine("\n");

			IStorable isStorable2 = theDoc as IStorable;
			if (isStorable != null)
			{
				isStorable2.Read();
				isStorable2.Write();
			}
		}

		static void Main()
		{
			Tester t = new Tester();
			t.Run();
		}
	}
}
