类是什么(50分)

H

huddle

Unregistered / Unconfirmed
GUEST, unregistred user!
书看了不少,还是不太理解。
能通俗地说一下什么是类(class)吗?
 
“人”就是一个类
男人,女人是“子类”继承自“人”这个类
又可以分出老人、小孩、白人等等子类!
人的身高、体重等是“属性”或“字段”
吃饭、跑步是“方法”
通俗吗?[:)]
 
上面果然够通俗。
就是爷爷到孙子对不对
 
如果是初学,可以暂不去管什么是类
 
类是数据与操作的集合
 
可以把类看作一种数据类型。
 
正是想结束初学阶段,所以要了解一下这个
 
类的关键是有继承性,有一个父类,它的子类在继承父类的基础上又有自己个性的东西。
大个比方吧。
一说“狗”,你肯定脑海里有一个大体的轮廓,两只耳朵,有尾巴(当然也有秃尾巴狗,:)),会叫,能吃东西。
狗的类

属性如下:
耳朵:2只
尾巴:1条
嘴 :一个。
动作:
叫声发出的处理过程。
咀嚼的过程。
消化过程

现在有两条狗,一条黑狗,一条斑点狗。
它们都有狗的基本属性,但还有个性。
在继承狗共同属性的基础上,再加上什么属性可以一个斑点狗啊?:)
没毛
身上有斑点
耳朵大
腿长
个头大
加上以上的属性,你就不简单是一个狗的概念了,更加具体了。
看看组件方面的书吧,派生组件就是很好的类的继承。自己做个试试。
 
天与地 这些都懂,我现在的问题是,如果与实际操作结果起来.
 
类是面向对象编程的精髓,具体的例子,楼上几位讲的也不错。但究竟用它来干什么呢?
我以前也很困惑,有位老友给我这样解释面向对象编程与结构化编程的区别。比如,汽车
是一个类,摩托车也是一个类,汽车有四个轮子,摩托车有两个,但怎么知道有几个轮子
这一属性呢?结构化编程通常会去一个一个数,而面向对象编程的做法是直接问,艾,汽
车,你有几个轮子,艾,摩托车,你呢?
 
to:蛐蛐 ,找个例子,做一个派生组件,通过添加自己定义的属性,并且是可视话的,
这样会帮助你理解的。
还有,继承是单向的。
 
 让我们先看一段代码:
  
  type
   TDate = class
   Mouth,day,Year:Integer;
   procedure SetValue(m,d,y:Integer);
   function LeapYear:Boolean;
  end;
  
  我们首先会看到class关键字,它的中文译名为“类”。类是一个非常重要的概
念。根据权威的定义,类是:一种用户定义的数据类型,它具有自己的说明和一些操
作。一个类中含有一些内部数据和一些过程或函数形式的对象方法,通常来描述一些非
常相似的对象
所具有的共同特征和行为。
  这个定义可能比较晦涩。你可以把类想象为一种特殊的Record类型,其中不但可能
包含数据,而且可能包含函数和过程(在OOP中称之为方法)。这些数据和方法被统称
为类的成员。
  上面这个类很显然是一个日期类型,它包括Mouth,Day,Year这三个数据成员,和
SetValue、LeapYear这两个方法。顺便说一句,在Delphi中,习惯以字母T作为每个类
的前缀,就象Viusal C++中习惯以字母C作为每个类的前缀一样。
  Mouth,Day,Year这三个数据成员指定了该日期的年、月、日。SetValue方法为这
三个数据成员赋值,而LeapYear检查当前日期所在的那一年是否是闰年。下面我们给出
这两个方法的实现部分:
  
  procedure TDate.SetValue(m,d,y):Integer;
  begin
   Mouth := m;
   Day := d;
   Year := y;
  end;
  
  function TDate.LeapYear:Boolean;
  begin
   if (Year mod 4 <> 0) then
    LeapYear := False
   else if (Year mod 100 <> 0)
    LeapYear := True
   else if (Year mod 400 <> 0)
    LeapYear := False
   else
    LeapYear := True;
  end;
  
  实现了这些定义之后,就可以这样调用它们:
  
  var
   ADay: TDate;
  begin
   //建立一个对象
   ADay := TDate.create;
   //使用之
   ADay.SetValue(1,1,2000);
   if ADay.LeapYear then
    ShowMessage('闰年:' + Inttostr(ADay.year));
   //释放对象
   ADay.free;
  end;
  
  我们来逐行解释这些代码的含义。var后面那一行声明了一个TDate类的变量。
  声明了变量之后,我们怎么使用它呢?使用TDate类的Create方法可以建立一个该
类的对象,并将其赋予ADay变量。
  现在我们又接触到了OOP中另一个重要的概念:对象。什么是对象?简言之,对象
就是类的实例,或者说,是类定义的数据类型的变量。当建立一个类的对象时,系统为
它分配一块内存。例如我们定义一个变量A为Integer类型,那么,Integer是一个数据
类型,A就是一个实例。类与对象的关系就类似于这两者之间的关系。区别类和对象是
非常重要的,甚至一些专业的程序员都往往将他们搞混。
  细心的读者可能注意到,在TDate类的定义中,并没有Create这个方法。那么这个
Create方法是从哪里来的呢?Create方法是每一个Class都具有隐含的方法,它的作用
是建立这个类的实例。请注意,在这里,类和其他的数据类型是不同的。其他的数据类
型都是声明了变量之后就可以直接使用,而类类型必须在使用Create方法创建它的实例
(对象)之后才能使用。
  事实上,在C++和其他大多数的OOP语言中,声明一个类的变量就能够同时建立起这
个类的对象。而Delphi(包括它的孪生兄弟C++Builder)在这方面与众不同,必须要
Create一下才能真正建立对象。同时,在这个对象不再需要时,必须要手工调用free方
法释放这个对象(当然,free方法也是每个类隐含的)。这和Delphi独特的“对象引用
模型”有关,有兴趣的朋友可以查阅有关资料,我就不多说了。
  这种情况造成了一个非常有趣的现象,那就是,编程的初学者往往忘记在使用对象
之前create它,从而出错,但从C++转向Delphi的高手也常常犯同样的错误……
  顺便告诉大家一个诀窍,当编译器出现“Read of Address: ffffffff”这样的错
误时,多半是因为在使用对象之前忘了Create,可以从这方面入手检查代码。另外,也
千万不要忘记在不需要它时使用free释放掉,否则可能造成内存泄漏。
  在建立和释放对象的代码的中间,是使用对象的代码。访问对象的数据成员非常简
单,和Record类型没有什么区别。可以点号表达式来访问它们:
  
  ADay.Year := 2000;
  ADay.Mouth := 1;
  ADay.Day := 1;
  
  同样,也可以使用点号表达式来调用对象的方法。如果你阅读了方法实现部分的代
码,你可以很容易地发现,ADay.SetValue1,1,2000)这一句分别为三个数据成员赋了
值,而ADay.LeapYear调用则返回当前日期所在年是否为闰年。至此,整段代码的意义
也就清楚了。
  然而,类不仅仅这么简单。上面这个例子是一个非常简单的类,可以直接访问它的
任何成员(数据和方法)。但某些类的成员是不能被随便访问的。Delphi中用三个关键
字区分这些成员的访问权限:
  
  表1

Private 该类型的成员只能在声明类中被访问
Public 该类型的成员可以被程序中的任何地方的代码访问
Protected 该类型的成员只能在声明类以及声明类的派生类中被访问
  
  Protected类型的成员以及什么是“派生类”等问题我们留到以后再进行讨论,现
在我们将注意力集中在前两者。
  Public类型就是在上面例子中的那种类型,这个很好理解。而Private类型,根据
表格中的简单解释,只能在该成员被声明的那个类(也就是该成员所属的那个类啦)中
被访问,越出这个界限,它就是不可见的。那么,Private类型的成员将如何被使用呢
?简单地说,就是通过一个Public类的方法来访问它。
  让我们看一个新的例子:
  
  type
   TDate = class
   private
   Mouth,day,Year:Integer;
   Public
   procedure SetValue(m,d,y:Integer);
   function LeapYear:Boolean;
   function GetText:String;
  end;
  
   在这个类中,Mouth,Day,Year这三个成员被声明为Private成员,因此它们在
类以外的其它地方是不可访问的。也就是说,如果你使用
  
  ADay.Year := 2000;
  
  这样的代码,那么编译器将会报错。但是,我们可以照样通过SetValue方法为它们
赋值:
  
  ADay.SetValue(1,1,2000);
  
  这行代码是合法的,因为SetValue本身是TDate类的成员,而且它又是一个Public
成员。而使用GetText方法则可以得到当前日期值(这也是得到当期日期值的唯一办
法)。
  这样的设置使得类的一些成员被隐含起来,用户只能用一些专门的方法来使用它
们。那些可以被外部代码访问的成员称之为类的接口。这样做有什么好处呢?首先,这
让类的作者可以检测被赋值的内容。比如,用户可能给一个对象赋予13月40日这样的无
效日期。而在隐含了一些成员之后,类的作者可以在方法的代码中检测这些值是否有
效,从而大大地减少了产生错误的机会。其次,使用规范的类,作者可以随时修改类内
部的代码,而使用该类的代码却无需任何修改!这样使得代码的维护成了一件轻松的事
件,特别是对于多人协作的大型软件而言。
  这就叫做数据的封装(encapsulation)。这是OOP的第一个特征。一个优秀的OOP
程序员,应该在设计类的时候,就确定将哪些重要的数据封装起来,并给出一个高效率
的接口。
  需要指出的一点是,表1中Private部分的论述对于“标准的”OOP语言(例如C++)
是完全正确的,但对于Delphi有一个例外。在Delphi中,Private成员除了在声明类中
可以访问外,在声明类所在的单元(.pas文件)中的任何地方都能被访问,不论这些代
码与声明
类的关系如何。严格来说,这是违反OOP的原则的,我不明白Borland为何要这么做(据
说是为了方便)。在关于Delphi的优劣性的讨论中,这是常被涉及的一个问题。
 
各位高手,你们当初怎么弄懂的?
 
是啊,你们当初是怎么懂的?
 
类就是一种包含数据和函数的数据类型!
 
任凭别人怎么描述你都很难理解,最好的方法就是自己去做个面向对象的程序,然后呢……嘿,再学习JAVA
 
我講不出
 
我不是高手,对于类也只是知之皮毛,至于怎么懂的,自己也不知道,只是在不停分析DELPHI
代码时豁然开朗的!我觉得上面那段左轻候的文章说的也很清楚呀!多读两遍一定会有所收获
的!
 
你就当类是一种自定义的数据类型,一般多用在需要增强祖先类的功能(继承父类的新类)或是开发组件时
 
请教一下,按我的理解,下面这段代码应该将控件label1的caption赋值为'start'
不过试下来不是这样,能说下为什么吗,多谢
我很菜,不过我很想脱菜:)
var
str:tlabel;
begin
str:=tlabel.Create(label1);
str.Caption:='start';
str.Free;
end;
 
顶部