کلاس های abstract

کلاس ها را همچنین می توان به صورت abstract تعریف کرد. از این نوع کلاس ها نمی توان instance ایی را ایجاد نمود. در این کلاس های پایه ، صرفا تعریف متدها و خواص هایی عنوان گردیده و در آینده در کلاس های فرزند توسعه داده خواهند شد. برای مثال :




کد:
public abstract class Named
{
    public abstract String Name {get; set;} // property
    public abstract void PrintName();       // method
}
public class B : Named
{
   private String name = "empty";
   public override String Name
   {
      get{return name;}
      set{name=value;}
   }
   public override void PrintName()
   {
      Console.WriteLine("Name is {0}", name);
   }
}
سوالی که شاید پیش بیاید این است که اگر interface ها صرفا تعریف توابع و خواص را می توانند در خود جای دهند پس چه دلیلی برای بکار بردن آنها و طولانی کردن کار کد نویسی وجود دارد؟
کاربردهای زیادی را می توان برای اینترفیس ها برشمرد. اینترفیس یک رفتار را تعریف می کند. فرض کنید در حال توسعه ی برنامه ایی هستید که بر روی دو کامپیوتر مختلف باید با هم در ارتباط مستقیم بوده و برهم کنش داشته باشند و هر برنامه از ماژولی به نام CCommObj communication object استفاده می نماید. یکی از متدهای این شیء ، SendData() می باشد که رشته ای را دریافت کرده و به برنامه ی دیگر می فرستد. این فراخوانی از نوع asynchronous است زیرا ما نمی خواهیم اگر خطایی در شبکه رخ داد، برنامه برای همیشه منتظر باقی بماند. اما چگونه برنامه ی A که تابع ذکر شده را فراخوانی کرده است می تواند تشخیص دهد که پیغام به مقصد رسیده است یا خیر و یا آیا خطایی در شبکه مانع رسیدن پیغام گشته است یا خیر؟ جواب بدین صورت است که CCommObj هنگام دریافت پیغام ، رخدادی را سبب خواهد شد و اگر خطایی رخ داده باشد خیر. در این حالت نیاز به یک ماژول logging نیز احساس می گردد تا خطاهای رخ داده را ثبت نماید. یک روش انجام آن این است که CCommObj پیاده سازی این امکان را نیز بعهده گرفته و اگر فردا نیز خواستیم ماژول دیگری را به برنامه اضافه کنیم هر روز باید CCommObj را تغییر دهیم. تمام این کارها را به سادگی می توان در یک اینترفیس مدل کرد. روش آن نیز در ادامه بیان می گردد:


در ابتدا یک اینترفیس ایجاد می کنیم تا لیست تمام امکانات ممکن را "منتشر" کند:



کد:
interface ICommObjEvents
{
	void OnDataSent();
	void OnError();
}
شی ء CCommObj ما از این توابع که بعدا توسعه داده خواهند شد برای با خبر سازی کلاینت ها استفاده می نماید. تمام متدها در یک اینترفیس ذاتا پابلیک هستند بنابراین نیازی به ذکر صریح این مطلب نمی باشد و اگر اینکار را انجام دهید کامپایلر خطای زیر را گوشزد خواهد کرد :



کد:
The modifier 'public' is not valid for this item
در ادامه کلاینت CClientApp_A را پیاده سازی خواهیم کرد :
کد:
class CClientApp_A:ICommObjEvents
{
	public void OnDataSent()
	{
		Console.WriteLine("OnDataSent");
	}
	public void OnError()
	{
		Console.WriteLine("OnError");
	}
	private CCommObj m_Server;
	public void Init(CCommObj theSource)
	{
		m_Server = theSource;
		theSource.Advise (this);
		string strAdd = ("N450:1");
		m_Server.read (strAdd,10);
	}
}
در کد فوق کلاس CClientApp_A از ICommObjEvents ارث برده و تمام متدهای این اینترفیس را پیاده سازی نموده است. هنگامی که CCommObj تابع OnDataSent را فراخوانی می کند این کلاینت پیغام را دریافت خواهد کرد. لازم به ذکر است که کلاس کلاینت ما چون از یک اینترفیس ارث بری می نماید پس باید تمام توابع و خواص کلاس پایه را پیاده سازی کند در غیر اینصورت هر چند برنامه کامپایل خواهد شد اما هنگامی که شیء CCommObj هر کدام از توابع این کلاس را فراخوانی کد ، خطای زمان اجرا رخ خواهد داد.
متد Init کلاس فوق آرگومانی را از نوع CCommObj دریافت نموده و در یک متغیر private آنرا ذخیره می نماید. همچنین در این متد ، متد Advise از کلاس CCommObj نیز فراخوانی گشته است.




کد:
public class CCommObj
{
	private int m_nIndex;
	public ICommObjEvents [] m_arSinkColl;
	public CCommObj()
	{
		m_arSinkColl = new ICommObjEvents[10];
		m_nIndex = 0;
	}
	public int Advise(ICommObjEvents theSink)
	{
		m_arSinkColl[m_nIndex] = theSink;
		int lCookie = m_nIndex;
		m_nIndex++;
		return lCookie
	}
	public void SendData(string strData)
	{
	foreach ( ICommObjEvents theSink in m_arSinkColl)
		if(theSink != null )
			theSink.OnDataSent ();
	}
}
این بحث ادامه دارد (لطفا با ما باشید و جایی نروید چون تازه بحث شیء گرایی شروع شده است!!) ....