posts - 3,  comments - 5,  trackbacks - 0
  2008年7月21日

  ●接口声明了一组相关的方法,在所有类之外

  ●抽象类是一种不完整的类定义,其中有些方法虽已声明,但没有定义

  从概念上说,接口定义了独立于类层次结构的应用编程接口(API).实际上,接口可以用于非OO的编程模型中,例如COM或CORBA这样的基于组件的模型.但是,您要将重点放在面向对象环境中的接口使用上,在这里它们也是很有用的.接口是终极封装,因为它们隐藏了实现这些方法的类的所有细节,只暴露出使用的接口.它们在只支持单继承(类只能从一个基类继承)的语言中尤其重要(实际上是必要的).如果一个类通过接口来展现它的成员函数,那么我们称它"实现"了这个接口.

  和接口不一样,抽象类是一个类:它可以拥有数据成员,可以是其他类的子类.但是和具体类(非抽象类)不同,它的某些行为故意留给其子类来定义.因此抽象类不能够实例化,只有具体类才能创建实例.

  接口几乎等价于没有任何数据成员和方法定义的抽象类.在C++中,这就是您定义接口的方法:声明一个没有数据成员,只有纯虚函数的类.像下面的例子这样:

  Class StatusCallback

      {

           public:

                   virtual void updateStatus(int oState,int nState) = 0;

       }

  然后,类可以从它派生,从而"实现"这个接口:

  Class MyClass:SomeOtherClass,StatusCallback

     {

           public:

                  void updateStatus(int oState,int nState)

                   {

                        if(nState > oState)

                          {

                             ......//do stuff

                           }

                    }

      }

  在Java中,接口通过interface关键字来定义: 

  public interface StatusCallback

      {

           void updateStatus(int oState,int nState);

       }

  然后接口由一个类来实现:

  public class MyClass implements StatusCallback

      {

           public void updateStatus(int oState,int nState)

            {

                  ......//do stuff

              }

                  ......//do stuff

       }

  在既支持接口又支持抽象类的语言中,您常会看到一种模式,即通过一个抽象类来提供一个接口的"缺省实现".例如,下面的接口:

  public interface XMLReader

   {

     public XMLObject fromString(String str);

              public XMLObject fromReader(Reader in);  

    }

       可能有这样的缺省实现:

  public abstract class XMLReaderImpl

        {

     public XMLObject fromString(String str)

                {

                     fromString(new StringReader(str));

                 }

               public abstract XMLObject fromReader(Reader in);

    }

  于是,需要实现XMLReader的程序员可以选择从XMLReaderImpl派生一个子类(也可能作为一个嵌套的类),只实现一个方法,而非两个方法.

posted @ 2008-07-21 19:15 肖斌 阅读(157) | 评论 (0)编辑
  2008年1月17日
  在操作系统中,死锁是很敏感的问题,很多意外的发生和死锁有着直接的关系,而死锁产生的原因有大概四种,我想了想,与其从如何解决死锁开始学习死锁,不如从制造死锁开始学习死锁.以下是我利用Monitor.Enter()制造的第一种死锁情况:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;


class Program
{
    static void Main(string[] args)
    {
        Add add1 = new Add ();
        Thread thread1 = new Thread (new ThreadStart (add1 .ThreadProc));
        Thread thread2 = new Thread(new ThreadStart(add1.ThreadProc));
        thread1.Start();
        thread2.Start();
        thread1.Join();
        thread2.Join();
        Console.WriteLine(add1.Result);
        Console.ReadLine();

    }
}

class Add
{
    protected int a = 0;
    protected void Update()
    {
        Monitor.Enter(this);
        a++;
    }
    public int Result
    {
        get
        {
            return a;
        }
    }
    public void ThreadProc()
    {
        for (int n = 0; n < 10; n++)
        {
            Update();
        }
    }
}

原理其实很简单,就是在进程thread1进行时占用a的使用权(通过Monitor.Enter(this)实现),然后故意不使用Monitor.Exit(this)释放使用权,这样,进程thread2在进行时需要使用a,但是,由于a已经进入了Monitor类的保护区,造成进程thread2无法访问,必须等待的状况,而同时,由于缺少了Monitor.Exit()的实现,a的使用权是不会被释放的,进程thread2一直等待,造成了死锁deadlock.

posted @ 2008-01-17 16:35 肖斌 阅读(42) | 评论 (1)编辑
  2008年1月16日
  特性(Attributes)感觉就象是一个帽子,它的使用和被它标注的元素(可以是类,方法或者字段)没有很大的关系,主要功能似乎只是用来描述被标注的元素.
  举例解释的话可能会有一点好,但是,不知道是否贴切:一个Class或者是Function在创作后需要知道编写它的作者的一些信息,比如名字,年龄,擅长,或者联系电话什么的,但是,这些东西无法在Class里面写入,因此,可以用特性来帮忙.
  我们将作者的所有信息写入到一个Class里面(一般情况下建议用属性(Property)和构造函数来输入一些信息),然后将其标注为特性类:
     class MyAttributes : Attributes
      {}
     然后将其标注在需要使用的元素上面,我们这里暂时描述Class:
     [MyAttributes()]
     public class A
     {}
     这样,一个特性的创建和使用便完成了.
  如何让代码知道我们的特性存在呢?关键就需要创建一个搜索特性的Class,这个类的目的是查找指定的类,看它是否具备了指定的特性,如果是,则完成相关操作,如果不是,就报错误或者执行其它的操作(甚至不做任何操作).
     因此,使用特性的步骤总共为四个步骤:
  1.创建一个特性类;
  2.将特性类和相关的元素联系起来;
  3.创建一个搜索类.
  4.利用搜索类进行搜索后执行相关的操作.
以下是个人实验的代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        Type t = typeof(Show);                    //将Show类的类型作为参数进行传递
        AuthorAttributesCheck aa = new AuthorAttributesCheck(t);  //通过AuthorAttributesCheck类来搜索看Show类是否存在特性类
        if (aa != null)                          //如果存在的话,就进行数据的读出
        {
            Console.WriteLine("The Author is {0} and {1}", aa.GetName(),aa.GetNotes ());
        }
        Console.ReadLine();
    }
}

public class Author:Attribute  //这个就是指明从Attribute继承出来的自定义特性
{
    protected string _name;
    protected string _notes;
    public Author (string name)
    {
        _name = name;
    }
    public string Name
    {
        get
        {
            return _name;
        }
    }
    public string Notes
    {
        get
        {
            return _notes;
        }
        set
        {
            _notes = value;
        }
    }
}


[Author("shaw")]     //在这里标注出特性,将它和Show类联系,即可得到Show类作者的信息
public class Show
{
    public Show ()
    {
        Console.WriteLine("YES");
    }
}

public class AuthorAttributesCheck
{
    protected Type _type;      //创建一个Type实例用来获得参数类型
    public AuthorAttributesCheck(Type type)
    {
        _type = type;
    }
    public string GetName()
    {
        foreach (Attribute attrib in _type.GetCustomAttributes(true))      //获得一个自定义特性数组
        {
            Author author = attrib as Author;                  //将特性实例和自定义特性数组做比较,看是否存在相同的数组
            if (attrib != null)
            {
                return author.Name;                       //如果存在的话,即说明type参数的类是被Author特性标注,因此,获取信息
            }
        }
        return null;
    }

    public string GetNotes()                          //获取Notes信息的方法
    {
        foreach (Attribute attrib in _type.GetCustomAttributes(true))
        {
            Author notes = attrib as Author;
            if(notes != null)
            {
                notes.Notes = "No.1";
                return notes.Notes;
            }
        }
        return null;
    }
}

posted @ 2008-01-16 17:05 肖斌 阅读(156) | 评论 (4)编辑