zoukankan      html  css  js  c++  java
  • 面向对象程序设计的概念

    OOP啊,给跪了

     

    1.1     简介

    在这一章中,我们将看到继承、重写等面向对象编程的概念是如何在C#中实现的。我们还将学习有关操作符的重载。

    1.2     构造函数

    构告函数是类中的方法,每次创建类的实例时,都将调用该方法。构造函数用于初始化成员变量。特点在于构造函数与类同名,并且不返回值。

    下面我们来研究下示例:

    示例1:

    using System;

    public class DaysInYear

    {

    private int days;

    public DaysInYear()

    {

    days=365;

    }

    static void Main(String[] args)

    {

    DaysInYear newDaysInYear=new DaysInYear();

    Console.WriteLine(newDaysInYear.days);

    }

    }

    以上示例说明,我们在实例化类的对象时,首先执行的便是类的构造函数。此示例最终显示结果为365,如果我们去掉构造函数,得到的将会是值类型变量days的默认值0。

    1.3     带参数的构造函数

    类是可以有多个构造函数的,可以将不同个数或不同类型的参数传递给这些构造函数,使它们产生不同的运行结果。

    我们来看看下面的例子:

    示例2:

    using System;

    public class DaysInYear

    {

    private int days;

    public DaysInYear()

    {

    days=365;

    }

    public DaysInYear(int day)

    {

    days=day;

    }

    public DaysInYear(String dayOne)

    {

    days=Convert.ToInt32(dayOne);

    }

    public void setDay(int newDays)

    {

    days=newDays;

    }

    static void Main(String[] args)

    {

    DaysInYear newDaysInYear=new DaysInYear();

    DaysInYear newDaysInYearInt=new DaysInYear(366);

    DaysInYear newDaysInYearSrt=new DaysInYear(“366”);

    Console.WriteLine(“默认值={0}”,newDaysInYear.days);

    Console.WriteLine(“传递的整型值={0}”,newDaysInYearInt.days);

    Console.WriteLine(“传递的字符串值={0}”,newDaysInYearStr.days);

    }

    }

    1.4     析构函数

    C#的析构函数由垃圾回收器调用。垃圾回收器是定期地、或在内存状态要求(内存已满)时执行清理工作。这是C#的高级机制。

    在之前我们已经讲过析构函数的实现方式了。那么我们接下来讲一下垃圾回收器是如何工作的。

    不能对结构使用析构函数。只能对类使用析构函数。

    一个类只能有一个析构函数。

    无法继承或重载析构函数。

    无法调用析构函数。它们是被自动调用的。

    析构函数既没有修饰符,也没有参数。

    1.4.1  垃圾回收器和析构函数

    垃圾回收器负责释放内存,这是通过销毁不再被引用或不再使用的对象。工作原理如下:

    如果为定义析构函数的对象分配了内存,运行库将把该对象添加到需要销毁的对象的列表中。运行库把析构函数当作销毁器,但在C#中,将它称为析构函数。

    垃圾回收器定期检查是否有未被引用的对象。

    如果找到了其名称没有列在销毁器列表中的对象,就立即清除该对象。

    如果对象名称列在需要销毁的对象列表中,则将它标记为“准备销毁”。

    完成垃圾回收后,将调用销毁器线程,该线程则调用所有标记为“准备销毁”的对象的销毁方法(析构函数)。

    对象销毁过程发生后,就将该对象从需要销毁的对象列表中删除。

    因为该对象没有被引用,也没有列在销毁器列表中,所以下次进行垃圾回收时就会清除该对象。

    当然,垃圾回收器也有某些缺陷。这些缺陷包括:

    有析构函数的对象占用的资料较多,因为即使不再需要它们,它们仍会在内存中驻留罗长的时间。

    销毁过程作为独立的线程执行,从而使资源被大量占用。

    所以,建议只在必要时才使用析构函数。

    1.5     C#中的方法重载

    在C#中,可以用以下两种方式重载方法:

    指定不同个数的参数

    指定不同参数的参数类型

    C#不支持对方法返回类型的重载

    在示例2中,我们已经看见构造函数的名称相同,但其中两个接收参数,有一个不接收

    参数。参数也有差别。这已经实现了构造函数重载。方法重载的方式与此类似。

    1.5.1  不同参数个数的方法重载

    我们研究一下示例:

    示例3:

    using System;

    public class Area

    {

    private int areaVal;

    public void AreaCal(int radius)

    {

    areaVal=(22/7) * radius * radius;

    }

    public void AreaCal(int length,int breadth)

    {

    areaVal=length * breadth;

    }

    public void AreaCal(int length, int breadth, int height)

    {

    areaVal=length * breadth * height;

    }

    static void Main(String[] args)

    {

    Area newArea=new Area();

    Console.WriteLine(newArea.areaVal);

    NewArea.AreaCal(6,8,10);

    Console.WriteLine(newArea.areaVal);

    NewArea.AreaCal(4,6);

    Console.WriteLine(newArea.areaVal);

    }

    }

    以上示例类Area的三个方法名称相同,都是AreaCal()。但是邮于使用不同个数的参数重载了这些方法。

    1.5.2  不同参数类型的方法重载

    另一种重载方法的方式是指定不同的参数类型。传弟的参数个数无关紧要。参数的个数可以相同。

    代码段2:

    public void AreaCal(Int radius)

    {

    areaVal=(22/7)* radius * radius;

    }

    public void AreaCal(string shapeName)

    {

    Console.WriteLine(“{0}”,shapeName);

    }

    1.5.3  操作符重载

    C#允许重载操作符。重载操作符意味着使操作符具有与其正常行为不同的行为。

    下面我们来研究两段代码,这两段代码使用方法执行两个整数变量的加法运算。

    代码段3:

    //第1行

    int result=Decimal.Add(54,200)

    //第2行

    int result2=54+200;

    第1行使用值类型为Decimail的数据函数类的Add方法计算变量result。第2行使用加法运算符”+”符号计算结果。两者完成的是同样的任务。但是使用操作符的优点是方便而且简单易于理解。假设要建立一个二次方程。或使用方法计算恒星与地球之间的距离的公式,那么不用操作符编写这种算式将是非常困难的。

    操作符可以使代码具有更好的可读性,同样,随着程序变得越来越复杂,将会有更多的类,那么这就间味着将要对这些对象执行很多运算。在这种情况下,重载操作符就会很有意义。重载操作符简化了对这些对象所执行的操作。当然也不是所有的操作符都可以重载的。重载操作符的方过程非常类似于创建方法的过程。所有重载的操作符都是静态方法。我们来看看可重载的操作符列表。

    表4.1:可以重载的操作符

    + - ! ~ ++ --

    * / % & | ^

    << >> != <, > <= >=

    示例4:

    using System;

    public struct Distance

    {

    public Distance(int lon, int mag)

    {

    this.longitude=lon;

    this.latitude=mag;

    }

    int longitude,latitude;

    public static Distance operator – (Distance first,Distance second)

    {

    return new Distance(first.longitude – second.longitude,first.latitude – second.latitude)

    }

    public static void Main()

    {

    Distance start =new Distance();

    Distance newDistance =new Distance();

    Distance finish =new Distance();

    start.longitude=12;

    start.latitude=10;

    finish.longitude=2;

    finish.latitude=1;

    newDistance=start – finish;

    Console.WirteLine(“坐标X轴为{0},Y轴为{1}”,newDistance.longitude,newDistance.latitude);

    }

    }

    在示例4中:

    声明一个名为Distance结构,它有两个名为longitude和latitude的数据成员。

    重载-(减号)操作符,当把结构为Distance的两个对象传递给它时该操作符执行两个对象的longitude和latitude分别相减,并返回Distance类型的另一个对象。

    在Main()函数中声明三个Distance类型的对象。我们已经设置对象start和finish的longitude和latitude。newDistance对象使用重载的操作符”-”来接受其它两个对象的longitude和latitude相减后的结果。

    将newDistance对象的longitude和latitude差值(即start减去finish对象的结果)显示给用户

    重载操作符的过程可以详细解释为下列步骤。

    请注意示例4的黑体部份,语法非常类似于声明方法的语法。

    首先指定访问修饰符。在该示例中,我们使用public 访问修饰符。

    关键字static使该操作符成为类的公共操作符,而不是特定对象的操作符。这是强制关建字。

    然后,我们定义操作符的返回类型。返回类型是操作符的结果所使用的类型。在该示例中,返回类型是Distance。

    在返回类型之后,指定关键字operator,该关键字必须在被子重载的操作符之前指定。这是强制关键字。

    然后必须指定被重载的操作符。要注意保证该操作符在表4.1中。

    必须指定该操作符执行运算时所用的参数。在该示例中,参数是两个Distance类型的对象。

    在该示例中,我们只是将所传递的两个对象的longitude和latitude相减,并用另一个Distance对象返回结果。减法的结果被传回Distance()方法,以便newDistance对象的longitude属性和latitude属性赋值。

    1.6     C#中的继承

    面向对象的编程可以将新类作为另一个类的后代来声明和使用。这个过程称为继承。继承使我们不用重写代码。并提供代码重用的巨大好处。C#中不支持多重继承,因为在应用程序变得很复杂时它会引起较大的混乱,并且就内存过载而言它也被视为效率不高的编程方式。现在我们学习一下单一继承。

    示例5:

    using System;

    class characterVal

    {

    public int setCharVal(char ch)

    {

    char charVal=ch;

    Console.WriteLine(“输入的字符是:{0}”, charVal);

    return(0);

    }

    }

    class StringVal : CharacterVal

    {

    public string strVal;

    public int setStrVal(string str)

    {

    strVal=str;

    Console.WriteLine(“输入的字符串是:{0}”,strVal);

    return(0);

    }

    }

    class Inheritance

    {

    StringVal objec1=new StringVal();

    object1.setCharVal(“j”);

    object1.setStrVal(“enjoy”);

    }

    示例5中,没有为类StringVal声明setCharVal()方法。我们创建了StringVal的对象object1。使用该object1对象,我们能够访问setCharVal方法。这是因为类StringVal继承了CharacterVal类。

    1.6.1  密封类

    在C#中,通过对类的继承进行密封可以避免对该类的继承。密封类使用的语法如下。

    代码段5:

    sealed class classOne

    {

    //类的实现

    }

    通过指定sealed关键字,可以密封任何类。此类保存在堆中。

    当类只包括静态成员时,可能需要必须密封该类。此外在某些情况下密封类可以提高应用程序的性能。

    1.7     C#中的方法重写

    我们已经知道在C#中如何实现继承。现在让我们考查如何实现方法重写。方法重写提供了重写或跳过基类的方法的灵活性。

    重写基类的方法时,我们在继续类或派生类中声明一个与基类中的方法同名的新方法,并在方法名称前附加new关键字。

    下面我们来研究下:

    示例6:

    using System;

    class intAddition

    {

    public void Add()

    {

    int firstNum=1;

    int secondNum=2;

    Console.WriteLine(“两数之和为:{0}”, firstNum+secondNum);

    }

    }

    class StringAddition :IntAdditon

    {

    new public Add()

    {

    string firstStr=”a”;

    string secondStr=”b”;

    Console.WriteLine(“两字符串之和为:{0}”,firstStr+secondStr);

    }

    }

    class MethodOverride

    {

    public static void Main()

    {

    StringAddition objStringAddition = new StringAddition();

    ObjStringAddition.add();

    }

    }

    示例输出结果为:ab

    在两个不同的类中都有一个名为Add()的方法。请注意,类StringAddition重官了类IntAddition中方法Add(),因为类StringAddition在定义add方法前指定了new关键字。注意的是就算没有指定new关键字,也是执行重写,输出结果也将相同。编译器会报没有生成new关键字的警告。使用new关键字是比较谨慎的编程做法。

    1.8     小结

    带参数的构造函数是接受参数的是构造函数。

    我们将不同个数或不同类型的参数传递给构造函数,以便运行库能够区分它们。

    在C#中,析构函数由垃圾回收器调用。

    垃圾回收器负责释放内存,这是通过销毁不再被引用的对象实现的。

    在C#中,可以用两种方式中的任何一种来重载方法。

    指定不同个数的参数

    指定不同类型的参数

    C#允许重载操作符

    重载操作符意味着使操作符(例如,加法操作符+)在应用于结构或类的特定对象时具有不同的行为。

    C#不支持多重继承。

    要重写基类的现有方法,需要在继承类中声明一个同名的新方法,并在方法名称前附加new关键字。

    1.9     练习

    1. 可以创建带参数的静态构造函数

    a.对 b.错

    2. 析构函数的语法是

    classMaster()

    {

    //析构函数的实现

    }

    a.对 b.错

    3. C#不支持_______________继承。

    a.单一 b.多重

    4. 可以使用____________关键字重写方法。

    a.Override b.new

    2.10 作业

    1. 在C#中创建一类EmplyTest,它有以下数据成员/字段

    标识符 类型 值

    EmplyNo Integer 接收输入

    EmplyName String Admin

    EmplyMoney Integer 接收输入

    及以下成员函数

    标识符 返回类型 参数

    CreateNewEmplyNo void Integer EmplyNo

    ShowEmplyName void String EmplyName

    CountEmplyMoney void Integer EmplyMoney

    EmplyTest类有构造函数,析构函数。一个无参构造函数,一个带一个参数的构造函数。参数为EmplyNo。另外重载ShowEmplyName方法改变参数为两个String类型的变量EmplyName,EmplyNameOne。

    再写一个子类,继承EmplyTest类,重写父类EmplyTest的ShowEmplyName方法。重写父类CountEmplyMoney方法,接收两个参数。EmplyNo及EmplyMoney,计算出他们的和赋给EmplyNo。打印出EmplyName.和EmplyNo。

    2. 创建成有以下数据成员的类Time:

    标识符 类型

    Hours Integer

    Minutes Integer

    Seconds Integer

    重载+操作符,用于将Seconds字段中包含的值加1。当Seconds的值等于60时,将Minutes的值加1,然后将Seconds的值恢复为0。同样当Minutes的值等于60时,必须执行下列操作:

    Minutes的值回复为0

    Seconds的值回复为0

    Hours的值加1

    当Hours的值等于24时,所有三个字段的值必须回复为0。必须将这三个字段的值用为参数传弟。编写Main()方法,实现上述功能,并在用户的控制台上显示输出结果。

    本文转自:http://www.cnntec.com

  • 相关阅读:
    重温spark基本原理
    hive拉链表以及退链例子笔记
    org.apache.hadoop.hive.ql.exec.DDLTask. MetaException错误问题
    skywalking部署
    【机器学习实战】第5章 Logistic回归
    【机器学习实战】第4章 基于概率论的分类方法:朴素贝叶斯
    【机器学习实战】第3章 决策树
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
  • 原文地址:https://www.cnblogs.com/kiwi/p/2436287.html
Copyright © 2011-2022 走看看