C#OOP之四 深入理解方法

举报
tea_year 发表于 2021/12/31 23:54:41 2021/12/31
【摘要】 视频:https://edu.csdn.net/course/detail/27107 方法深入研究 方法是完成特定功能的代码集。举例来类比一下,比如一台电视,我们开启电视开关之后,我们不需要去理解电视是如何选台、和电视台联系上而播放的步骤,只需要知道会开关电视、选台等就可以了。所以,方法就象一个被封闭的起来...

视频:https://edu.csdn.net/course/detail/27107

方法深入研究

方法是完成特定功能的代码集。举例来类比一下,比如一台电视,我们开启电视开关之后,我们不需要去理解电视是如何选台、和电视台联系上而播放的步骤,只需要知道会开关电视、选台等就可以了。所以,方法就象一个被封闭的起来的功能操作。

 

 

访问修饰符

     封装就是使某些信息隐藏起来,但是,对于一定范围的信息仍是可见的。

封装是面向对象三大特性之一。主要是为了一.避免非法数据的访问;二.保证数据的完整性。

我们可以通过访问修饰符来实现封装。C#支持以下如下访问修饰符:

访问修饰符是一些关键字,用于指定声明的成员或类型的可访问性。

    世间万物皆有一定的存在或活动范围,比如你是中国人,那么你的活动范围大部分在中国,如果你要去国外你就得办个护照。再比如你是郑州海洋馆的一只热带鱼,那么别人要来看你,至少要买张门票。世间万物的这种活动和访问范围的机制使世界可以有条不紊的运作。对象或对象成员属性和方法也需要通过某种机制来约束其访问,所以就有了访问修饰符这些东东。

本节介绍四个访问修饰符:

n        public

n        protected

n        internal

n        private

使用这些访问修饰符可指定下列五个可访问性级别:

声明的可访问性

含义

public

访问不受限制。

protected

访问仅限于包含类或从包含类派生的类型。

internal

访问仅限于当前程序集。

protected internal

访问仅限于从包含类派生的当前程序集或类型。

private

访问仅限于包含类型。

 

切记前面有分号,表示分隔.

项目1:模拟CS游戏中警察的程序

 项目背景:对于每位玩过第一人称射击类游戏的朋友来说,CS不能不被反复提起。我们以里面的警察为例,来学习一下访问修饰符符的用处与区别。

解决方案:通过修改访问修饰符,来观察了解访问修饰符的作用范围。

任务1:编写代码,在UltraEdit中编写如下代码,并尝试修改访问修饰符。

/*

功能:实现一款游戏中的一个角色的定义

时间:2015/09/08

作者:张

版本:1.0

*/

 


    
  1. usingSystem;
  2. classPolice
  3. {
  4. //属性:Police的成员变量;
  5. private int id; //private:私有的?何为私有:只能被类本身来访问;
  6. private string NickName; //昵称
  7. private string Clothes; //衣服
  8. //行为:成员方法
  9. public void SetInfo() //设置警察信息方法
  10. {
  11. id=888; //这些信息不应该放在Game类里,而应该由Police类的对象来操作;同样访问一个类的成员变量需要,使用对象.成员变量
  12. NickName="菜青虫";
  13. Clothes="绿色迷彩服";
  14. }
  15. public void Display()
  16. {
  17. Console.WriteLine("Id:"+id+"昵称:"+NickName+" 衣服:"+Clothes); //显示一下信息
  18. }
  19. public void Pao() //成员方法定义:[访问修饰符][返回类型]方法名(参数列表){方法代码}
  20. {
  21. Console.WriteLine("跑@....");
  22. }
  23. public void Zou()
  24. {
  25. Console.WriteLine("走#....");
  26. }
  27. public void Sheji()
  28. {
  29. Console.WriteLine("射击DDDDDD");
  30. }
  31. }
  32. class Game
  33. {
  34. static void Main() //程序的入口处
  35. {
  36. Police kiki=newPolice();
  37. //尝试在此处直接访问类的成员变量
  38. //kiki.id=”007”;kiki.NickName=”金头云”
  39. kiki.SetInfo();
  40. kiki.Display();
  41. kiki.Pao(); //对象名.方法()
  42. kiki.Zou();
  43. kiki.Sheji();
  44. Console.ReadLine();
  45. }
  46. }
 

 

2.选择文件à保存,以保存该文件,并以Police.cs结束。

3.编译并运行该程序。

4.观察测试不同访问修饰符的区别异同。

 

 

方法的定义

方法是类的组成元素,而方法本身又是由很多代码组成的,这些代码也可以包含对方法的调用。事实上,我们在前面的章节已经不止一次用过方法了,例如Main(),我们一直在使用这个方法。方法的定义包括

<访问修饰符><返回类型> 方法名  (形式参数列表)

{

       方法体

}

方法命名规则和变量名命名规则一样,方法名应该反映对象行为的含义。

方法的参数列表表示方法接受的处理数据,很多时候事务的行为需要一定的处理数据行为才能正常执行。比如说洗衣机的处理数据是要洗的衣服,动物“吃”方法的处理数据是吃的东西等等。参数列表可以是以下形式:

void  eat(); //空参数,不需要参数

void eat(string sPork); //一个形式参数sPork (简称形参)

void eat(string  sEgg,int  iNum);   //两个形式参数(sEgg,iNum)

void eat(string sEgg,int iNum,string sAddress);//三个形式参数(sEgg,iNum,sAddress)"

方法调用:eat(“猪肉”)   //注意在此处传入的值”猪肉”为实际参数(简称实参)

方法体指要在方法中执行的代码,它是该方法的详细处理步骤。比如洗衣机的“洗衣”方法里面就包括详细洗衣的步骤,比如左转20圈然后右转20圈、洗衣20分钟、甩干等。

返回类型用关键字return,return语句使用时重点要注意以下几个问题:

n       一个方法中可以出现多个return语句,但只有一个会被执行;

n       返回值的数据类型必须与方法定义返回值数据类型相同;

n       如果方法定义了返回值则必须使用return语句进行返回;

n       当遇到return语句时,方法执行将终止,执行被中断并退出方法;

下面来看一下计算器的程序,看是否仍有需要提高的地方。

/*

功能:实现一个非常简单的计算器,根据客户的要求来进行+ - * /运算;

时间:2015/09/09 ;在第三章Demo\Switch基础上完善

作者:张

版本:2.1.3

*/

 


    
  1. using System;
  2. class Calc //Calc类完成的功能是什么?用户输入和计算;输入应该放到客户端来实现,但是此处留个小尾巴.到4.0扩展;
  3. {
  4. //1.成员变量
  5. double x,y; //1.声明两个变量
  6. char op; //op表示操作符; //注意比较:int、char、string的使用,使用哪个更好一些。
  7. //2.成员方法
  8. public void Shuru()
  9. {
  10. Console.WriteLine("请输入第一个操作数:");
  11. x=Convert.ToDouble(Console.ReadLine());
  12. Console.WriteLine("请输入第二个操作数:");
  13. y=Convert.ToDouble(Console.ReadLine());
  14. }
  15. public void Jisuan()
  16. {
  17. Console.WriteLine("请输入您要进行的运算:+ - * /");
  18. op=Convert.ToChar(Console.ReadLine()); //因为op是char型的,需要强制转换;
  19. switch(op)
  20. {
  21. case '+':
  22. Console.WriteLine("和为:"+(x+y));
  23. break;
  24. case '-':
  25. Console.WriteLine("差为:"+(x-y));
  26. break;
  27. case '*':
  28. Console.WriteLine("积为:"+(x*y));
  29. break;
  30. case '/':
  31. if(y==0)
  32. Console.WriteLine("除数不能为0");
  33. else
  34. Console.WriteLine("商为:"+(x/y));
  35. break;
  36. default:
  37. Console.WriteLine("错误选择:");
  38. break;
  39. }
  40. }
  41. }
  42. //***************************************客户端类
  43. class CalcGUI
  44. {
  45. static void Main()
  46. {
  47. Calc jisuanqi=new Calc();
  48. jisuanqi.Shuru();
  49. jisuanqi.Jisuan();
  50. }
  51. }
 

 

该版本的计算器中已经很好的实现了,业务逻辑(计算功能)和界面(客户端:输入)的功能,但是依据OO的原则,应该具有良好的扩展性和复用性,如果在此时,需要增加新的功能则必须再次修改swich中的内容,并且输出功能也应该在客户端实现。因此,此程序仍有完善的必要。下面请大家做项目2,实现业务逻辑与客户端分离的程序。

项目2:计算器:将计算功能和用户输入、输出功能分离

 项目背景:剖析计算器,更好的体会OO扩展性、复用性的好处。

解决方案:使用带返回值的方法来解决.

任务1:编写代码

/*

功能:实现计算器;将计算功能和用户输入分离

时间:2015/09/09 星期二  第二节课

版本:4.1.1

*/

 


    
  1. usingSystem;
  2. classCalc
  3. {
  4. //Calc类的成员变量x,y
  5. private double x,y;
  6. private double result; //再增加一个结果变量
  7. public void ShuRu()
  8. {
  9. //在此接受x,y的值
  10. Console.WriteLine("请输入第一个操作数:");
  11. x=Convert.ToDouble(Console.ReadLine());
  12. Console.WriteLine("请输入第二个操作数:");
  13. y=Convert.ToDouble(Console.ReadLine());
  14. }
  15. public double Jia()
  16. {
  17. result=x+y;
  18. return result;
  19. }
  20. public double Jian()
  21. {
  22. result=x-y;
  23. return result;
  24. }
  25. public double Cheng()
  26. {
  27. result=x*y;
  28. return result;
  29. }
  30. public double Chu()
  31. {
  32. if(y==0)
  33. return 0; //注意此处是有问题的,考虑如何修改
  34. else
  35. {
  36. result=x/y;
  37. return result;
  38. }
  39. }
  40. }
  41. /**********客户端类,即界面类***********/
  42. classClacGUI
  43. {
  44. static void Main()
  45. {
  46. Calc jisuanqi; //jisuanqi=?
  47. jisuanqi=new Calc();
  48. jisuanqi.ShuRu();
  49. Console.WriteLine(“和”+jisuanqi.Jia()); //返回double型的和-->数
  50. Console.WriteLine(“差”+jisuanqi.Jian()); //返回double型的差-->数
  51. Console.WriteLine(“积”+jisuanqi.Cheng()); //返回double型的积-->数
  52. Console.WriteLine(“商”+jisuanqi.Chu()); //返回double型的商-->字符串
  53. //doublex,y; //在Main()方法内,所以说不是ClacGUI的成员变量.叫什么呢?(考察的知识点,为变量的作用域)
  54. }
  55. }
 

 

任务2:保存程序为Calc4.cs,并编译程序

任务3:运行程序Calc4

任务4:体会本程序与Calc3的区别,考虑改进在何处,是否仍有改进的余地。

任务5:扩充,使用没有返回值的方法,使用返回类型为string的方法如何做?

 

项目3:计算器:使用带参数的方法

 项目背景:剖析计算器,更好的体会OO扩展性、复用性的好处。在原有计算器的基础上增加求平方、求阶乘的功能。

解决方案:使用带返回值及带参数的方法来解决.

任务1:编写代码

/*

功能:实现计算器;将计算功能和用户输入分离

时间:2015/09/09 星期二  第二节课

版本:5.1.1

*/

 


    
  1. usingSystem;
  2. classCalc
  3. {
  4. private double result; //再增加一个结果变量
  5. public double Jia(double num1,double num2) //加法运算:形参:num1,num2
  6. {
  7. result=num1+num2;
  8. returnresult;
  9. }
  10. publicdouble Jian(double num1,double num2) //减法运算
  11. {
  12. result=num1-num2;
  13. returnresult;
  14. }
  15. publicdouble Cheng(double num1,double num2) //乘法运算
  16. {
  17. result=num1*num2;
  18. returnresult;
  19. }
  20. publicdouble Chu(double num1,double num2) //除法运算
  21. {
  22. result=num1/num2;
  23. returnresult;
  24. }
  25. publicdouble PingFang(double num1)
  26. {
  27. result=num1*num1;
  28. returnresult;
  29. }
  30. publicdouble NciFang(double num1,double num2) //num1:2的num2:5次方
  31. {
  32. result=1; //定义result为1
  33. for(inti=1;i<=num2;i++)
  34. {
  35. result=result*num1;
  36. }
  37. return result;
  38. }
  39. }
  40. /**********客户端类,即界面类***********/
  41. classClacGUI
  42. {
  43. static void Main()
  44. {
  45. Calc jisuanqi; //jisuanqi=?
  46. jisuanqi=new Calc();
  47. double x,y; //x,y为Main()的局部变量
  48. Console.Write("请输入第一个数字:");
  49. x=Convert.ToDouble(Console.ReadLine());
  50. Console.Write("请输入第二个数字:");
  51. y=Convert.ToDouble(Console.ReadLine());
  52. char op; //op为Main()的局部变量,表示操作符
  53. Console.Write("请输入您要进行的运算:+ - * / ^:"); //^:表示求N次方
  54. op=Convert.ToChar(Console.ReadLine());
  55. switch(op)
  56. {
  57. case '+': //加运算
  58. Console.WriteLine(jisuanqi.Jia(x,y));
  59. break;
  60. case '-':
  61. Console.WriteLine(jisuanqi.Jian(x,y));
  62. break;
  63. case '*': //加运算
  64. Console.WriteLine(jisuanqi.Cheng(x,y));
  65. break;
  66. case '/':
  67. if(y==0)
  68. Console.WriteLine("除数不能为0");
  69. else
  70. Console.WriteLine(jisuanqi.Chu(x,y));
  71. break;
  72. case '^':
  73. Console.WriteLine(jisuanqi.NciFang(x,y));
  74. break;
  75. default:
  76. Console.WriteLine("其他无效选择!!!");
  77. break;
  78. }
  79. }
  80. }
 

 

任务2:保存文件,并编译程序

任务3:运行程序

任务4:体会参数在方法中的应用。

 

 

 

方法参数:值参数、引用参数、输出参数

值参数:声明方法时,不带任何修饰符号的是值参数,一个值参数相当于一个局部变量。当使用值参数时,将会分配一个新的存储位置,将实参的值拷贝到这个位置,并且将此拷贝传递给该方法。允许方法将新值传递给值参数,但是这样的赋值只影响实参的副本,而不影响在方法调用时由调用方法给出的实参。被调用方法不会修改内存中实参的值,所以,使用值参数时可以保证实参值是安全的。

简而言之:值参数只能将值带进方法,不能将值带出方法。

案例:二数字交换

 


    
  1. //NotSwap.cs
  2. // 值参数不能影响实参的值
  3. usingSystem;
  4. classTest
  5. {
  6. static void NotSwap(int x, int y)
  7. {
  8. Console.WriteLine("进入NotSwap时:x = {0}, y = {1}", x, y);
  9. int temp = x;
  10. x = y;
  11. y = temp;
  12. Console.WriteLine("退出NotSwap时:x = {0}, y = {1}", x, y);
  13. }
  14. static void Main()
  15. {
  16. int i = 1, j = 2;
  17. Console.WriteLine("执行NotSwap前:i = {0}, j = {1}", i, j);
  18. NotSwap(i, j);
  19. Console.WriteLine("执行NotSwap后:i = {0}, j = {1}", i, j);
  20. }
  21. }
 

 

程序运行效果是值参数的值仅仅在方法体内被改变,而不能影响对应的实参的值。

引用参数:

用ref修饰符声明的参数是引用参数。与值参数不同,引用参数不能创建新的存储位置,用参数表示的存储位置就是在方法调用中,作为实际参数对应的变量所表示的存储位置。

变量在作为引用参数传递之前,必须先明确赋值。

简而言之:引用参数既能将值带进方法,也能将值带出方法。

案例:二数交换

//Swap.cs

// 引用参数会影响实参的值

 


    
  1. usingSystem;
  2. classTest
  3. {
  4. static void Swap(ref int x, ref int y)
  5. {
  6. Console.WriteLine("进入Swap时:x = {0}, y = {1}", x, y);
  7. int temp = x;
  8. x = y;
  9. y = temp;
  10. Console.WriteLine("退出Swap时:x = {0}, y = {1}", x, y);
  11. }
  12. static void Main()
  13. {
  14. int i = 1, j = 2;
  15. Console.WriteLine("执行Swap前:i = {0}, j = {1}", i, j);
  16. Swap(ref i, ref j);
  17. Console.WriteLine("执行Swap后:i = {0}, j = {1}", i, j);
  18. }
  19. }
  20. 输出参数:
  21. out修饰的参数是输出参数,其他同ref参数一样,在使用之前无须赋值,必须在方法内完成对象的初始化。
  22. 简而言之:输出参数不能将值带进方法,只能将值带出方法。
  23. 案例:将路径分解为目录名和文件名的方法SplitPath,需要返回目录名和文件名两个值。
  24. //SplitPath.cs
  25. // 利用输出参数来返回多个值
  26. usingSystem;
  27. classTest
  28. {
  29. static void SplitPath(string path, outstring dir, out string name)
  30. {
  31. int i = path.Length;
  32. while (i > 0)
  33. {
  34. char ch = path[i-1];
  35. if (ch == '\\' || ch == '/'|| ch == ':')
  36. break;
  37. i--;
  38. }
  39. dir = path.Substring(0, i);
  40. name = path.Substring(i);
  41. }
  42. static void Main()
  43. {
  44. string dir, name;
  45. SplitPath("c:\\Windows\\System\\hello.txt",out dir, out name);
  46. Console.WriteLine("目录名: {0}",dir);
  47. Console.WriteLine("文件名: {0}", name);
  48. }
  49. }
 

 

 

 

 

静态方法与实例方法

static:用来修饰静态成员和静态方法;

没有使用static修饰的成员和方法为实例成员和实例方法;

区别如下:

ü       静态成员、方法属于类,被类的所有实例共享;实例成员、方法属于对象(类的实例),每个对象都有实例成员的不同副本。

ü       静态成员只标识一个存储位置,无论创建了多少个类的实例,它的静态成员在内存中都只占同一块区域;类的实例成员属于类的实例所有,每创建一个类的实例,都在内存中为实例成员开辟一块区域。

ü       静态成员、方法通过类名.运算符来使用;实例成员、方法通过对象名. 运算符来使用。

ü       静态方法只能访问类中的静态成员,而不能使用实例成员。

在前面的Console类的WriteLine、Write等方法就是静态方法,是通过类Console来引用的。

案例:使用账户Account类获取银行信息的静态方法PrintBankInfo

 


    
  1. //Account2.cs
  2. // 演示方法的声明和调用
  3. usingSystem;
  4. classAccount
  5. {
  6. private decimal balance;
  7. private string name;
  8. public Account(string name)
  9. {
  10. this.balance = 0;
  11. this.name = name;
  12. Print("开户", 0);
  13. }
  14. public bool Deposit(decimal amount)
  15. {
  16. if (amount <= 0)
  17. return false;
  18. balance += amount;
  19. Print("存入", amount);
  20. return true;
  21. }
  22. public bool Withdraw(decimal amount)
  23. {
  24. if (amount > balance || amount <=0)
  25. return false;
  26. balance -= amount;
  27. Print("取出", amount);
  28. return true;
  29. }
  30. private void Print(string operation,decimal amount)
  31. {
  32. Console.WriteLine("---------------------------");
  33. Console.WriteLine("姓名: {0}", name);
  34. Console.WriteLine("{0}: {1}",operation, amount);
  35. Console.WriteLine("余额: {0}", balance);
  36. Console.WriteLine("---------------------------");
  37. }
  38. public static void PrintBankInfo()
  39. {
  40. Console.WriteLine("---------------------------");
  41. Console.WriteLine(" XYZ银行, 电话: 12345678");
  42. Console.WriteLine("---------------------------");
  43. Console.WriteLine(" 顾客至上 服务第一 ");
  44. Console.WriteLine("---------------------------");
  45. }
  46. public static void Main()
  47. {
  48. Account.PrintBankInfo();
  49. Account acc = new Account("张三");
  50. bool succeed = acc.Deposit(100);
  51. if (!succeed)
  52. Console.WriteLine("存款失败!");
  53. succeed = acc.Withdraw(37);
  54. if (!succeed)
  55. Console.WriteLine("取款失败!");
  56. }
  57. }
 

 

有时候使用静态方法非常方便。对于常用的“工具”方法一般都使用静态方法啦实现,比如Math类。

 

 

 

实践问题:

选择题:

1.      说明以下语句是正确的还是错误的

封装意味着防止访问不需要的信息()

2.     请注意以下语句

语句A :静态变量即使在执行它们所属的函数后仍然保持其原值。

语句B:静态函数可以访问静态以及非静态的变量。

以下那项是正确的?

a.A和B都正确

b.A正确,B错误

c.A 错误,B正确

d.A和B都是错误

3.判断以下语句是正确的还是错误的:

在公共访问区分符中,基类的所有公共成员都是受保护的。

抽象代表对象或类的基本特性,这些特性使得它们能够与其他对象或类区别开来。

 

 

小结:

在本章中,我们主要学习了:

u      访问修饰符的分类和使用范围

u      参数化方法的几种方式

u      静态方法和静态变量

 

 

英语词汇:

英文             全文                                        中文

Public                                                      公共的、公开的

Private                                                     私有的

Protected                                                受保护的

Internal                                             内部的

Access                                                    访问

Outside                                            外部的

Definition                                                 定义

Operator                                                 操作符

Model                                                     模型

Set                                                          设置

Get                                                          得到

Error                                                              错误

Area                                                               区域

Specifier                                                      修饰符

Return                                                            返回

Method                                                   方法

Parameterparameter list                                        参数

List                                                          列表

Following                                                       下面的

Factorial                                                            阶乘

Out                                                                          输出的

Ref  reference                                                    引用

Example                                                  例子

Count                                                             计数

 

 

练习项目:

                编写一个程序,该程序要计算用户输入的数的阶乘。请使用静态和静态变量创建此程序。提示:用户输入数的极限是1-20。

 

 

 


 

文章来源: aaaedu.blog.csdn.net,作者:tea_year,版权归原作者所有,如需转载,请联系作者。

原文链接:aaaedu.blog.csdn.net/article/details/51245597

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。