这篇篇文章我主要通过两个例子(计算器和猜拳游戏)来理解面向对象。
使用面向对象编程,关键的是要找出重复的东西,然后把它抽象出来,进行封装。所以,我们先来看下计算器计算的时候,哪些是重复的。重复的可作为属性。
先看计算器的例子。我们先模拟下计算的场景。当用户打开计算器的时候,先需要输入第一个要计算的数字,然后选择运算符,接下来输入第二个要计算的数字,最后得出计算结果。这里面,每次计算的时候,都涉及到要输入的数字,运算符,这三个是变量,所以我们把它们抽象出来,放到一个计算类Calc中。然后在点击计算的时候运算即可。代码如下:
Calc类:
1 public class Calc 2 { 3 public double Number1 { get; set; } 4 public double Number2 { get; set; } 5 6 public double Calculate(string sign) 7 { 8 double r; 9 switch (sign) 10 { 11 case "+": 12 r = this.Number1 + this.Number2; 13 break; 14 case "-": 15 r = this.Number1 - this.Number2; 16 break; 17 case "*": 18 r = this.Number1 * this.Number2; 19 break; 20 case "/": 21 r = this.Number1 / this.Number2; 22 break; 23 default: 24 throw new Exception("参数错误!"); 25 } 26 return r; 27 } 28 }
计算方法:
1 namespace 面线对象实现计算器 2 { 3 public partial class Form1 : Form 4 { 5 public Form1() 6 { 7 InitializeComponent(); 8 } 9 10 private void btnEquals_Click(object sender, EventArgs e) 11 { 12 Calc c = new Calc(); 13 c.Number1 = Convert.ToDouble(txtNumber1.Text); 14 c.Number2 = Convert.ToDouble(txtNumber2.Text); 15 16 string sign = cmbSign.Text; 17 18 try 19 { 20 txtResult.Text = c.Calculate(sign).ToString(); 21 } 22 catch (Exception ex) 23 { 24 MessageBox.Show(ex.Message); 25 } 26 27 } 28 } 29 }
接下来我们看下面向过程的编程。
1 public partial class Form2 : Form 2 { 3 public Form2() 4 { 5 InitializeComponent(); 6 } 7 8 private void btnEquals_Click(object sender, EventArgs e) 9 { 10 double n1 = Convert.ToDouble(txtNumber1.Text); 11 double n2 = Convert.ToDouble(txtNumber2.Text); 12 try 13 { 14 string sign = cmbSign.Text; 15 double r; 16 switch (sign) 17 { 18 case "+": 19 r = n1 + n2; 20 break; 21 case "-": 22 r = n1 - n2; 23 break; 24 case "*": 25 r = n1 * n2; 26 break; 27 case "/": 28 r = n1 / n2; 29 break; 30 default: 31 throw new Exception("参数错误!"); 32 } 33 34 txtResult.Text = r.ToString(); 35 } 36 catch (Exception ex) 37 { 38 MessageBox.Show(ex.Message); 39 } 40 } 41 }
这样看来面向对象和面向过程好像没什么区别,那为什么还要用面向对象呢?假如,我现在不想用WinForm窗口实现计算器,想改成控制台程序。如果用面向对象编程,只要把Calc类复制过去就实现了整个算法,而面向过程却要把calc中算法全部重写。二者的区别在这里就开始体现了。当然这个计算器还能进一步优化,这个后续再说。
接下来看猜拳游戏。
首先模拟下游戏的场景。当用户点击剪刀时,你出:显示剪刀,电脑随机出,然后比较输赢。这里涉及到的对象有你,电脑。涉及到的属性有,剪刀,石头,布,每个对象都出拳的方法。每个角色都要有个保存出拳结果的属性。既然电脑和你的属性和方法都相同,那能否把这两个对象合并成一个对象呢?最好不要。因为你出拳是用户在界面点击,然后把参数传进去,电脑是随机出拳,可以在方法中随机生成,不传参数,两个方法的参数不一致,分开更好维护。比较输赢的方法不能存在于你和电脑中,因为裁判必须是第三方。为方便判断输赢,我们把出拳结果用数字表示,石头=1,剪刀=2,布=3,用用户出拳减去电脑出拳的结果来表示输赢,很容易得出用户-电脑=-1或者2的时候,玩家赢,用户-电脑=0的时候,表示平局,其余是玩家输。所以,整个猜拳游戏的代码如下:
出拳的枚举:
1 namespace 猜拳游戏 2 { 3 public enum Fist 4 { 5 stone=1, 6 scissors=2, 7 cloth=3 8 } 9 }
玩家类:
1 namespace 猜拳游戏 2 { 3 public class Person 4 { 5 public int PFist { get; set; } 6 7 public void ShowFist(int index) 8 { 9 this.PFist = index; 10 } 11 } 12 }
电脑类:
1 namespace 猜拳游戏 2 { 3 public class Computer 4 { 5 public int CFist { get; set; } 6 7 public void ShowFist() 8 { 9 Random rd = new Random(); 10 int r =rd.Next(1,4); 11 this.CFist = r; 12 } 13 } 14 }
裁判类:
1 namespace 猜拳游戏 2 { 3 public class Judgement 4 { 5 /// <summary> 6 /// 猜拳判断输赢 玩家赢=1;平局=0;玩家输=-1 7 /// </summary> 8 /// <param name="p">玩家</param> 9 /// <param name="c">电脑</param> 10 /// <returns></returns> 11 public int Judge(int p,int c) 12 { 13 int r; 14 if (p - c == -1 || p - c == 2) 15 { 16 r = 1; 17 } 18 else if (p - c == 0) 19 { 20 r = 0; 21 } 22 else 23 { 24 r = -1; 25 } 26 return r; 27 } 28 } 29 }
这里要特别提示下:
裁判判断的结果是输赢,这里最好不要直接返回类似“你赢了”之类的信息,返回数字即可,因为用户可能会把“你赢了”改成“You Win !”等任何其他提示信息。
窗体类中的代码:
1 private void btnGuessStone_Click(object sender, EventArgs e) 2 { 3 Computer c = new Computer(); 4 c.ShowFist(); 5 lblComputerResult.Text = c.CFist == (int)Fist.stone ? "石头" : (c.CFist == (int)Fist.scissors ? "剪刀" : "布"); 6 7 8 Person p = new Person(); 9 p.ShowFist((int)Fist.stone); 10 lblYouResult.Text = p.PFist == (int)Fist.stone ? "石头" : ""; 11 12 Judgement j = new Judgement(); 13 int r= j.Judge(p.PFist,c.CFist); 14 15 string result = string.Empty; 16 //猜拳判断输赢,返回值=0:平局;返回值的绝对值=1:玩家赢;返回值的绝对值=2:玩家输。 17 if (r == 0) 18 { 19 result = "平局,再来一局!"; 20 } 21 if (r==1) 22 { 23 result = "你赢了!!!"; 24 } 25 if (r == -1) 26 { 27 result = "你输了!!!"; 28 } 29 30 lblResult.Text = result; 31 } 32 33 private void btnGuessScissors_Click(object sender, EventArgs e) 34 { 35 Computer c = new Computer(); 36 c.ShowFist(); 37 lblComputerResult.Text = c.CFist == (int)Fist.stone ? "石头" : (c.CFist == (int)Fist.scissors ? "剪刀" : "布"); 38 39 40 Person p = new Person(); 41 p.ShowFist((int)Fist.scissors); 42 lblYouResult.Text = p.PFist == (int)Fist.scissors ? "剪刀" : ""; 43 44 Judgement j = new Judgement(); 45 int r = j.Judge(p.PFist, c.CFist); 46 47 string result = string.Empty; 48 //猜拳判断输赢,返回值=0:平局;=1:玩家赢;-1:玩家输。 49 if (r == 0) 50 { 51 result = "平局,再来一局!"; 52 } 53 if (r == 1) 54 { 55 result = "你赢了!!!"; 56 } 57 if (r == -1) 58 { 59 result = "你输了!!!"; 60 } 61 62 lblResult.Text = result; 63 } 64 65 private void btnGuessCloth_Click(object sender, EventArgs e) 66 { 67 Computer c = new Computer(); 68 c.ShowFist(); 69 lblComputerResult.Text = c.CFist == (int)Fist.stone ? "石头" : (c.CFist == (int)Fist.scissors ? "剪刀" : "布"); 70 71 72 Person p = new Person(); 73 p.ShowFist((int)Fist.cloth); 74 lblYouResult.Text = p.PFist == (int)Fist.cloth ? "布" : ""; 75 76 Judgement j = new Judgement(); 77 int r = j.Judge(p.PFist, c.CFist); 78 79 string result = string.Empty; 80 //猜拳判断输赢,返回值=0:平局;1:玩家输;2:玩家赢。 81 if (r == 0) 82 { 83 result = "平局,再来一局!"; 84 } 85 if (r == 1) 86 { 87 result = "你赢了!!!"; 88 } 89 if (r == -1) 90 { 91 result = "你输了!!!"; 92 } 93 94 lblResult.Text = result; 95 }
以上就是面向对象的两个例子,可能表述的不是很完整,后期会反复雕琢,欢迎指正!