成员重载是指在同一个类型中创建两个或两个以上的成员,这些成员具有相同的名字,唯一不同的是参数的数量或参数的类型。因为只有方法、构造函数以及索引属性有参数,所以只有这些成员可以被重载。
ü 在一族对参数的数量进行重载的成员中,较长的重载应该用参数名来说明与之对应的较短的重载所使用的默认值。这最适用于布尔型参数。
例如:
public class Type
{
public MethodInfo GetMethod(string name); //ignoreCase=false
public MethodInfo GetMethod(string name, Boolean ignoreCase);
//用ignoreCase而不用caseSensitive
}
û 避免在重载中随意地给参数命名。如果两个重载中的某个参数表示相同的输入,那么该参数的名字应该相同。
例如:
public class String
{
//correct
public int IndexOf(string value){…}
public int IndexOf(string value, int startIndex){…}
//incorrect
public int IndexOf(string value){…}
public int IndexOf(string str, int startIndex)
}
û 避免使重载成员的参数顺序不一致。在所有的重载中,同名的参数应该出现在相同的位置。
例如:
public class EventLog
{
public EventLog();
public EventLog(string logName);
public EventLog(string logName, string machineName);
public EventLog(string logName, string machineName, string source)
}
只有在一些非常特殊的情况下才能打破这条非常严格的规则。
例如:params数组参数必须是参数列表中的最后一个参数。
参数列表中包含输出参数,这些参数一般出现在参数列表的最后。
ü 如果需要可扩展性,要把最长的重载做成虚函数,较短的重载应该仅仅是调用较长的重载。
public class String
{
public int IndexOf(string s)
{
return IndexOf(s, 0);
}
public int IndexOf(string s, int startIndex)
{
retirm IndexOf(s, startIndex, s.Length)
}
public virtual int IndexOf(string s, int startIndex, int count)
{…}
}
û 不要在重载成员中使用 ref 或 out 修饰符。
例如:
public class SomeType
{
public void SomeType(string name){…}
public void SomeType(out string name){…}
}
ü 如果方法有可选的引用类型参数,要允许它为null,以表示应该使用默认值。
if (geometry == null) DrawGeometry(brush, pen);
else DrawGeometry(brush, pen, geometry);
ü 要优先使用成员重载,而不是定义有默认参数的成员,默认参数不符合CLS规范。
//4.0的新特性
public static void Show(string msg = "")
{
Console.WriteLine("Hello {0}",msg);
}
如果显式实现接口成员,客户代码在调用这些接口成员时,必须把实例强制转换为接口类型。
例如:
public struct Int32:IConvertible
{
int IConvertible.ToInt32(){…}
}
客户代码:
int i = 0;
i.ToInt32(); //编译不通过
((IConvertible)i).ToInt32(); //编译通过
û 尽量避免显式实现接口成员。
ü 如果希望接口成员只能通过该接口来调用,可考虑显式地实现接口成员。
例如:设计ICollection<T>.IsReadOnly 的主要目的是为了让数据绑定基础设施通过ICollection<T>接口来访问。在使用该接口类型时,几乎不会直接访问该方法。因此List<T>显示实现了该接口成员。
ü 当需要隐藏一个成员,并增加一个名字更合适的等价成员时,可考虑显式实现接口成员。
public class FileStream:IDisposable
{
IDisposable.Diopose(){Close();}
public void Close(){…}
}
ü 如果希望让派生类实现功能定制,要为显式实现的接口成员提供一个功能相同的受保护的虚方法。
[Serializable]
public class List<T>:ISerializable
{
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
GetObjectData(info, context)
}
protected virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{…}
}
方法表示操作,属性表示数据,如果其他各方面都一样,那么应该使用属性而不是方法。
ü 如果成员表示类型的逻辑attribute,考虑使用属性。
例如:Button.Color是属性,因为color是button的一个attribute。
ü 如果属性的值储存在内存中,而提供属性的目的仅仅是访问该值,要使用属性不要使用方法。
public Customer
{
private string name;
public Customer(string name)
{
this.name = name;
}
public string Name
{
get {return this.name;}
}
}
ü 要在下列情况下使用方法而不要使用属性:
Ø 操作开销较大。
Ø 操作是一个转换操作,如Object.ToString方法。
Ø 即使传入的参数不变,操作每次返回的结果都不同,如:Guid.NewGuid方法。
Ø 操作返回一个数组。
ü 如果不应该让调用方改变属性的值,要创建只读属性。
û 不要提供只写属性,也不要让设置方法的存取范围比获取方法更广。
例如:不要把属性的设置方法设置为公有,而把获取方法设为受保护。
ü 要为所有属性提供合理的默认值。
ü 要允许用户以任何顺序来设属性的值。
ü 如果属性的设置方法抛出异常,要保留属性原来的值。
û 避免在属性的获取方法中抛出异常。
索引属性通常称为索引器,它的调用语法与数组索引相似。
public class String
{
public char this[int index]
{
get {…}
}
}
…
string city = “suzhou”;
Console.WriteLine(city[0]);
ü 考虑通过索引器的方式让用户访问存储在内部数组中的数据。
û 避免有一个以上参数的索引器。
û 避免用System.Int32、System.Int64、System.String、System.Object、枚举或泛型参数之外的类型来做索引器的参数。
û 不要同时提供语义上等价的索引器和方法。
有时候为用户提供通知事件来告诉他们属性值发生了改变是有用的。例如,System.Windows.Forms.Control在它的text属性值发生改变后会触发TextChange事件。
public class Control : Component
{
string text = String.Empty;
public event EventHandler<EventArgs> TextChanged;
public string Text
{
get { return text; }
set
{
if (text != value)
{
text = value;
OnTextChanged();
}
}
}
protected virtual void OnTextChanged()
{
EventHandler<EventArgs> handler = TextChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
ü 考虑在高层API(通常是设计器组件)的属性值被修改时触发属性改变的通知事件。
ü 考虑在属性值被外界修改时触发通知事件。
有两种类型的构造函数:类型构造函数和实例构造函数。
public class Customer
{
public Customer {…} //实例构造函数
static Customer {…} //类型构造函数
}
类型构造函数时静态的,CLR会在使用该类型之前运行它。实例构造函数在类型的实例创建时运行。类型构造函数不能带任何参数,实例构造函数则可以。
ü 考虑提供简单的构造函数,最好是默认构造函数。
ü 要把构造函数的参数用作设置主要属性的便捷方法。
ü 如果构造函数参数用于简单的设置属性,要使用相同的名字命名构造函数参数和属性。
public class EventLog
{
public EventLog(string logName)
{
this.logName = logName;
}
public string LogName()
{
get {…}
set {…}
}
}
ü 要在构造函数中做最少的工作。
ü 要在类中显式地声明公用的默认构造函数。
û 避免在结构中显式地定义默认构造函数。
û 避免在对象的构造函数内部调用虚成员。
例如:它会在Derived的新实例创建时打印出“What’s wrong?”。
public abstract class Base
{
public Base()
{
Method();
}
分享到:
相关推荐
本资料提供的“chapter4”文件包含了第四章习题的参考答案,学习者可以通过比对自己解答与参考答案,找出错误并理解正确解题思路,从而加深对C语言的理解。这种自我评估的过程对于提高编程技能至关重要,因为编程...
综上所述,JAVA语言程序设计中的第四章方法涵盖了方法的基本概念、定义、参数、调用、重载、访问控制、成员方法以及特殊方法等多个方面。理解并熟练运用这些知识点对于成为一名合格的JAVA开发者至关重要。在学习过程...
在Java程序设计的学习过程中,第四章通常涵盖了面向对象编程的核心概念。这包括类、对象、封装、继承和多态等核心特性。以下是对这些知识点的详细解析: 1. **类与对象**:类是Java中的蓝图,它定义了对象的状态...
King的经典教材,第二版中第4章的习题涵盖了C语言的核心概念和编程技巧。本章重点讨论了指针、数组以及它们在程序设计中的应用,这些都是C语言的核心内容。下面将详细阐述这些知识点。 一、指针 1. 指针的定义:...
C#程序设计第三章类的高级成员 类是面向对象的程序设计的基本构成模块,类是一种数据结构,这种数据结构可能包含数据成员,函数成员以及其它的嵌套类型。数据成员类型有常量、字段、事件,函数成员类型有方法、属性...
C++程序设计课件:第15章 静态成员与友元 本章主要内容包括静态成员和友元两个部分。静态成员是类中的成员,是类的一部分,在类外不可任意访问,从而起到保护作用。静态成员有静态数据成员和静态成员函数之分。 ...
### 软件设计师教程(第三版)第一章 #### 知识点概览与解析 根据提供的信息,本文档将围绕“软件设计师教程(第三版)”的第一章展开,主要聚焦于软考中级软件设计师的相关知识点。由于原教程文档较大,故将其...
本节内容主要围绕“Java语言程序设计_第4章_类的重用”展开,通过“第4章 类的重用(熊).ppt”的课件和源代码,我们将深入探讨这个主题。 首先,类的重用主要体现在两个方面:继承(Inheritance)和接口...
【标题】"ACCP6.0 S1 C#语言 和 数据库技术基础 第4章(共17章)" 涵盖了编程初学者在学习C#语言和数据库技术时的重要基础知识。作为北大青鸟ACCP6.0_S1课程的一部分,这个章节主要面向那些希望通过Java语言进入IT...
C++ 语言程序设计第七章 本节课件主要讲解了 C++ 语言中的类的继承与派生,涵盖了继承的定义、目的、继承方式、类成员的访问控制等重要知识点。 一、继承的定义 继承是指在已有类的基础上新增自己的特性而产生新...
《C程序设计(第五版)》是谭浩强教授的经典著作,对于学习C语言的初学者来说,是一本非常实用的教材。第九章通常会深入讲解C语言中的指针概念,这是C语言的一个核心特性,也是许多编程难题的解决关键。在这一章,...
### Java语言设计基础篇第九章课后习题解析 #### 9.1 题目解析:矩形类实现及应用实例 **题目背景:** 本题要求设计一个`Rectangle`类来表示矩形,该类包含宽度和高度两个属性,并提供计算面积和周长的方法。同时...
在"Java语言程序设计(郑莉)第八章课后习题答案"这个文档中,我们可以预见到包含以下知识点的详细解答: 1. **类与对象**:Java是一种面向对象的编程语言,类是对象的模板,对象是类的实例。习题可能涉及创建类,...
本资源是 C++ 程序设计教程面向对象分册的第一章答案,涵盖了基本的 C++ 程序设计概念和面向对象编程的基本原则。 1. 选择题答案: * 1.C:正确的 C++ 语句是使用分号结尾。 * 2.B:C++ 中的基本数据类型包括整数...
第六章是程序设计的一个关键部分,通常涵盖更高级的概念和技术,包括函数、指针、结构体以及内存管理等核心主题。下面,我们将深入探讨这些知识点,并结合习题来提升你的理解。 1. **函数**: 函数在C语言中是代码...