(原创)c#学习笔记09--定义类01--c#中的类定义

第九章 定义类

  本章内容:

    ●  如何在C#中定义类和接口

    ●  如何使用控制可访问性和继承的关键字

    ●  System.Object类及其在类定义中的作用

    ●  如何使用VS和VCE提供的一些帮助工具

    ●  如何定义类库

    ●  接口和抽象类的异同

    ●  结构类型的更多内容

    ●  复制对象的一些重要信息

9.1  C#中的类定义

  C#使用class关键字来定义类:

      class MyClass
      {
          // Class members.
      }

  默认情况下,类声明为内部的,即只有当前项目中的代码才能访问它。可以使用internal访问修饰符关键字显式指定,如下所示(但这是不必要的):

      internal class MyClass
      {
          // Class members.
      }

  另外,还可以指定类是公共的,应该可以由其他项目中的代码来访问。为此,要使用关键字public。

      public class MyClass
      {
          // Class members.
      }

  note: 以这种方式声明的类不能是私有或受保护的。可以把这些声明类的修饰符用于声明类成员,详见第10章。

  除了这两个访问修饰符关键字外,还可以指定类是抽象的(不能实例化,只能继承,可以有抽象成员)或密封的(sealed,不能继承)。为此,可以使用两个互斥的关键字 abstract 或 sealed。所以,抽象类必须用下述方式声明:

      public abstract class MyClass
      {
          // Class members, may be abstract.
      } 

  其中MyClass是一个公共抽象类,也可以是内部抽象类。

  密封类的声明如下所示:

      public sealed class MyClass
      {
          // Class members.
      }

  与抽象类一样,密封类也可以是公共或内部的。

  还可以在类定义中指定继承。为此,要在类名的后面加上一个冒号,其后是基类名,例如:

      public class MyClass : MyBase
      {
          // Class members.
      }

  注意,在C#的类定义中,只能有一个基类,如果继承了一个抽象类,就必须实现所继承的所有抽象成员(除非派生类也是抽象的)。

  编译器不允许派生类的可访问性高于基类。也就是说,内部类可以继承于一个公共基类,但公共类不能继承于一个内部类。因此,下边代码是合法的:

      public class MyBase
      {
          // Class members.
      }
      internal class MyClass : MyBase
      {
          // Class members.
      }

  但下述代码不能编译:

      internal class MyBase
      {
          // Class members.
      } 

      public class MyClass : MyBase
      {
          // Class members.
      }

  如果没有使用基类,则被定义的类就只继承于基类 System.Object(它在 C#中的别名是 object)。毕竟,在继承层次结构中,所有类的根都是System.Object。

  除了以这种方式指定基类外,还可以在冒号之后指定支持的接口。如果指定了基类,它必须紧跟在冒号的后面,之后才是指定的接口。如果没有指定基类,则接口就跟在冒号的后面。必须使用逗号分隔基类名(如果有基类)和接口名。

  例如,给MyClass添加一个接口,如下所示:

      public class MyClass : IMyInterface
      {
          // Class members.
      }

  所有接口成员都必须在支持该接口的类中实现,但如果不想使用给定的接口成员,就可以提供一个“空”的实现方式(没有函数代码)。还可以把接口成员实现为抽象类中的抽象成员。

  下面的声明是无效的,因为基类MyBase不是继承列表中的第一项:

      public class MyClass : IMyInterface, MyBase
      {
          // Class members.
      }

  指定基类和接口的正确方式如下:

      public class MyClass : MyBase, IMyInterface
      {
          // Class members.
      }

  可以指定多个接口,所以下列代码是有效的:

      public class MyClass : MyBase, IMyInterface, IMySecondInterface
      {
            // Class members.
      } 

  表9-1是类定义中可以使用的访问修饰符的组合。

  

  

接口的定义

  声明接口的方式与声明类的方式相似,但使用的关键字是interface,而不是class,例如:

      interface IMyInterface
      {
          // Interface members.
      }

  访问修饰符关键字public和internal的使用方式是相同的,与类一样,接口也默认定义为内部接口。所以要使接口可以公开访问,必须使用public关键字:

      public interface IMyInterface
      {
          // Interface members.
      }

  不能在接口中使用关键字 abstract 和 sealed,因为这两个修饰符在接口定义中是没有意义的(它们不包含实现代码,所且不能直接实例化,且必须是可以继承的)。

  接口的继承也可以用与类继承类似的方式来指定。主要的区别是可以使用多个基接口,例如:

      public interface IMyInterface : IMyBaseInterface, IMyBaseInterface2
      {
          // Interface members.
      }

  接口不是类,所以没有继承System.Object。但是为了方便起见,System.Object的成员可以通过接口类型的变量来访问。如上所述,不能用实例化类的方式来实例化接口。下面的实例提供了一些类定义的代码和使用它们的代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ch09Ex01
{
    public abstract class MyBase
    {

    }

    internal class MyClass : MyBase
    {

    }

    public interface IMyBaseInterface
    {

    }

    internal interface IMyBaseInterface2
    {

    }

    internal interface IMyInterface : IMyBaseInterface, IMyBaseInterface2
    {

    }

    internal sealed class MyComplexClass : MyClass, IMyInterface
    {

    }

    class Program
    {
        static void Main(string[] args)
        {
            MyComplexClass myObj = new MyComplexClass();
            Console.WriteLine(myObj.ToString());
            Console.ReadKey();
        }
    }
}

  执行项目,结果如图所示。

  

示例的说明

  这个项目在下面的继承层次结构中定义了类和接口,如图9-2所示。

  

  这里包含 Program,是因为这个类的定义方式与其他类的定义方式相同,而它不是主要类层次结构中的一部分。这个类处理的Main()方法是应用程序的入口点。

  Main()中的代码调用MyComplexClass的一个实例myObj的ToString()方法:

      MyComplexClass myObj = new MyComplexClass();
      Console.WriteLine(myObj.ToString());

  这是继承自 System.Object 的一个方法(图中没有显示,该图省略了这个类的成员,使图变得更清晰),并把对象的类名作为一个字符串返回,该类名用任意相关的命名空间来限定(本例中的命名空间为:Ch09Ex01)。

  

时间: 2024-10-26 23:25:31

(原创)c#学习笔记09--定义类01--c#中的类定义的相关文章

【VC++学习笔记四】MFC应用程序中框架类的获取

一.文档类中 获取视图: 先获取主窗体,在根据主窗体获取视图 pMain->GetActiveDocument();注意类型转换 由于文档中可能包含多个视图,可以按照下面函数获取: CView*   CTestDoc::GetView(CRuntimeClass*   pClass) { CView*  pView; POSITION   pos=GetFirstViewPosition(); while(pos!=NULL) { pView=GetNextView(pos); if(!pVie

Directx11学习笔记【二】 将HelloWin封装成类

我们把上一个教程的代码封装到一个类中来方便以后的使用. 首先新建一个空工程叫做MyHelloWin,添加一个main.cpp文件,然后新建一个类叫做MyWindow,将于窗体有关的操作封装到里面 MyWindow.h文件 1 /************************************************************************ 2 Directx11学习笔记[2] 将HelloWin封装成类 3 2016.01 by zhangbaochong 4 /

Puppet学习笔记(CentOS6.3+Puppet3.01)

Puppet学习笔记(CentOS6.3+Puppet3.01) 技术 Add comments Oct262012 下了决心,好好学习puppet,周末专门去参加一个puppet的培训,难得朋友那么热心,组织大家一起去学习.我就提前做一下功课. 2012年10月29日:参加完两天的培训,深刻体会到puppet的强悍,当然讲Puppet的朋友,还是非常有经验,不只是puppet经验,还有讲课的经验,学习一个新东西的经验.一个最大的收获:官方的文档非常好,把puppet读完,你就差不多. Cont

C++ Primer 学习笔记_64_重载操作符与转换 --转换与类类型【下】

重载操作符与转换 --转换与类类型[下] 四.重载确定和类的实参 在需要转换函数的实参时,编译器自动应用类的转换操作符或构造函数.因此,应该在函数确定期间考虑类转换操作符.函数重载确定由三步组成: 1)确定候选函数集合:这些是与被调用函数同名的函数. 2)选择可行的函数:这些是形参数目和类型与函数调用中的实参相匹配的候选函数.选择可行函数时,如果有转换操作,编译器还要确定需要哪个转换操作来匹配每个形参. 3)选择最佳匹配的函数.为了确定最佳匹配,对将实参转换为对应形参所需的类型转换进行分类.对于

C++ Primer 学习笔记_83_模板与泛型编程 --一个泛型句柄类

模板与泛型编程 --一个泛型句柄类 引言: [小心地雷] 这个例子体现了C++相当复杂的语言应用,理解它需要很好地理解继承和模板.在熟悉了这些特性之后再研究这个例子也许会帮助.另一方面,这个例子还能很好地测试你对这些特性的理解程度. 前面示例的Sales_item和Query两个类的使用计数的实现是相同的.这类问题非常适合于泛型编程:可以定义类模板管理指针和进行使用计数.原本不相关的Sales_item类型和 Query类型,可通过使用该模板进行公共的使用计数工作而得以简化.至于是公开还是隐藏下

C++ GUI Qt4学习笔记09

C++ GUI Qt4学习笔记09 qtc++ 本章介绍Qt中的拖放 拖放是一个应用程序内或者多个应用程序之间传递信息的一种直观的现代操作方式.除了剪贴板提供支持外,通常它还提供数据移动和复制的功能. QMimeData是一个可以提供不同格式数据的类. 9.1使拖放生效 拖放操作有两个动作:拖动和放下.Qt窗口部件可以作为拖动点.放下点或者同时作为拖动点和放下点. 9.2支持自定义拖动类型 9.3剪贴板处理技术 多数应用程序都通过某一种或者几种方式来使用Qt的内置剪贴板处理技术. C++ GUI

C++ Primer 学习笔记_69_面向对象编程 --继承情况下的类作用域

面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:如果不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这种类作用域的层次嵌套使我们能够直接访问基类的成员,就好像这些成员是派生类成员一样: Bulk_item bulk; cout << bulk.book() << endl; 名字book的使用将这样确定[先派生->后基类]: 1)bulk是Bulk_item类对象,在Bulk_item类中查找,找不到名

C++ Primer 学习笔记_58_重载操作符与转换 --重载操作符的定义

重载操作符与转换 --重载操作符的定义 引言: 明智地使用操作符重载可以使类类型的使用像内置类型一样直观! 重载操作符的定义 重载操作符是具有特殊名称的函数:保留字operator后接定义的操作符符号.如: Sales_item operator+(const Sales_item &,const Sales_item &); 除了函数调用操作符之外,重载操作符的形参数目(包括成员函数的隐式this指针)与操作符的操作数数目相同.函数调用操作符可以接受任意数目的操作数. 1.重载的操作符名

C++ Primer 学习笔记_63_重载操作符与转换 --转换与类类型【上】

重载操作符与转换 --转换与类类型[上] 引言: 在前面我们提到过:可以用一个实参调用的非explicit构造函数定义一个隐式转换.当提供了实参类型的对象需要一个类类型的对象时,编译器将使用该转换.于是:这种构造函数定义了到类类型的转换. 除了定义到类类型的转换之外,还可以定义从类类型到其他类型的转换.即:我们可以定义转换操作符,给定类类型的对象,该操作符将产生其他类型的对象.和其他转换一样,编译器将自动应用这个转换. 一.转换为什么有用? 定义一个SmallInt的类,该类实现安全小整数,这个

《机电传动控制》学习笔记09

<机电传动控制>学习笔记09 胡恒谦 机卓1301 1. 电力电子器件 电力电子器件根据其导通和关断可控性的不同可以分为以下三类. (1)不可控型器件,即导通与关断都不能控制的器件.仅整流二极管是不可控器件. (2)半控型器件,即只能控制其导通,不能控制其关断的器件.普通晶闸管SCR及其派生器件属于半控型器件. (3)全控型器件,即导通与关断都可以控制的器件.GTR.GTO.IGBT等都属于全控型器件. 2. 晶闸管 晶闸管导通条件为:加正向电压且门极有触发电流:其派生器件有:快速晶闸管,双向