470 likes | 595 Views
類別與物件 II (Classes and Objects II). 鄭士康 國立台灣大學 電機工程學系 / 電信工程研究所 / 資訊網路與多媒體研究所. 程式 DiceSimulation.Program (1/3). using System; namespace DiceSimulation { /* * 模擬擲骰子示範類別的宣告與物件的使用 * 使用類別 Dice 的建構 函式 * 3/23/2008 */ class Program {
E N D
類別與物件 II(Classes and Objects II) 鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
程式 DiceSimulation.Program (1/3) using System; namespace DiceSimulation { /* * 模擬擲骰子示範類別的宣告與物件的使用 * 使用類別Dice的建構函式 * 3/23/2008 */ class Program { static void Main(string[] args) {
程式 DiceSimulation.Program (2/3) int[] count = new int[6]; // 累計點數出現次數 for (int i = 0; i < 6; ++i) { count[i] = 0; } const int N = 12000; // 總擲骰次數 int seed = 123; Dice dice = new Dice( seed ); int faceValue; // 擲骰N次 for (int i = 0; i < N; ++i) { faceValue = dice.FaceValue; ++count[faceValue-1]; dice.Toss(); }
程式 DiceSimulation.Program (3/3) // 印出結果 for (int i = 0; i < 6; ++i) { Console.WriteLine(" {0} appears {1} times ", i + 1, count[i]); } } } }
程式 DiceSimulation.Dice (1/2) using System; namespace DiceSimulation { /* * 骰子 * 3/23/2008 */ public class Dice { int faceValue; Random rand; public Dice() { rand = new Random(); Toss(); }
程式 DiceSimulation.Dice (2/2) public Dice(int seed) { rand = new Random(seed); Toss(); } public int FaceValue { get { return faceValue; } set { faceValue = value; } } public void Toss() { faceValue = rand.Next() % 6 + 1; } } }
建構函式與解構函式(Constructor and Destructor) • 預設建構函式(default constructor) • 具參數之建構函式 • 檢驗參數範圍 • 解構函式
物件產生與消滅流程 static void main( string[] arg ) { public Dice(int seed) { . . . } Dice dice = new Dice( seed ); 物件宣告 物件生成 ~Dice() { . . . } } 刪除物件dice 離開主函數, 程式結束
存取修飾詞(Access Modifiers) • public • private • protected • internal
練習 • 修改類別Card,改用建構函式設定初值,以屬性取得suit及faceValue Card suit : char faceValue : int Suit FaceValue
程式 UsingStatic.Program (1/2) using System; namespace UsingStatic { /* 示範靜態成員之使用 * 3/27/2007 */ class Program { static void Main(string[] args) { Console.WriteLine( "請輸入要轉換的小時數與天數, 以一個空格分開"); string[] input = (Console.ReadLine()).Split(' '); int hours = int.Parse(input[0]); int days = int.Parse(input[1]);
程式 UsingStatic.Program (2/2) int hoursToMins = TimeConversion.HoursToMins(hours); int daysToHours = TimeConversion.DaysToHours(days); Console.WriteLine(hours + " hours = " + hoursToMins + " minutes"); Console.WriteLine(days + " days = " + daysToHours + " hours"); Test t1 = new Test(); Test t2 = new Test(); Console.WriteLine(Test.GetNConstructed + " Test objects were constructed"); Console.ReadLine(); } } }
程式 UsingStatic.TimeConversion (1/2) using System; namespace UsingStatic { /* * collection of time conversion routines * 3/27/2007 */ public static class TimeConversion { private const int HOURS_PER_DAY = 24; private const int MINS_PER_HOUR = 60;
程式 UsingStatic.TimeConversion (2/2) public static int HoursToMins( int hours ) { return hours*MINS_PER_HOUR; } public static int DaysToHours( int days ) { return days*HOURS_PER_DAY; } } }
程式 UsingStatic.Test using System; namespace UsingStatic { public class Test { private static int nConstructed = 0; public Test(){ ++nConstructed; } public static int GetNConstructed{ get{ return nConstructed; } } } }
靜態成員與靜態類別 • 常數宣告 • 靜態成員應用場合 • 靜態函式Main • 靜態類別應用場合
靜態成員的記憶配置 t1 記憶體地址1 函式Test()進入地址 t2 函式Test()進入地址 記憶體地址2 函式成員Test進入點 Test nConstructed 記憶體地址 函式成員 GetNConstructed進入點
練習 (1/2) • 在類別Card內增加靜態成員函式,累計產生的Card物件數 • 寫一程式利用類別Card產生全副撲克牌,放在陣列deck內
練習 (2/2) • 實作並測試一靜態類別EqSolver,內含兩靜態成員函式double Linear(double a, double b)及double Quadratic(double a, double b, double c)分別解一次方程式a x + b = 0及a x2 + b x + c = 0
運算子多載 • 可以多載 • 一元:+、-、!、~、++、--、true、false • 二元:+、-、*、/、%、&、|、^、<<、>>、==、!=、>、<、>=、<= • 不可多載 • =、.、&&、||、?:、[] 、() 、->、new、is、sizeof、typeof、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>= • 轉換運算子 • explicit 關鍵字 • Implicit 關鍵字
UsingOperOverload.Program(1/2) using System; namespace UsingOperOverload { /* 示範一元運算子多載 * 4/9/2007 */ class Program { static void Main(string[] args) { Rectangle rec = new Rectangle(100, 50); Console.WriteLine("長方形rec的面積: " + rec.Area());
UsingOperOverload.Program(2/2) rec++; Console.WriteLine("長方形rec++後的面積: " + rec.Area()); // 應為 5151 ++rec; Console.WriteLine("長方形++rec後的面積: " + rec.Area()); // 應為 5304 Console.ReadLine(); } } }
UsingOperOverload.Rectangle(1/2) using System; namespace UsingOperOverload { public class Rectangle { private int width; private int length; private int area; public Rectangle(int width, int length) { this.width = width; this.length = length; area = width * length; }
UsingOperOverload.Rectangle(2/2) public int Area() { return area; } public static Rectangle operator ++(Rectangle op) { Rectangle result = new Rectangle(op.width+1, op.length+1); return result; } } }
UsingOperOverload2.Program(1/2) using System; namespace UsingOperOverload2 { /* * 示範二元運算子多載的應用 * 4/9/2007 */ class Program { static void Main(string[] args) { Rectangle rec1 = new Rectangle(100, 50); Rectangle rec2 = new Rectangle(90, 25); Rectangle recSum = rec1 + rec2; Rectangle recDif = rec1 - rec2;
UsingOperOverload2.Program(2/2) // recSum.Area() 應為14250 Console.WriteLine("rec1 + rec2 的面積: " + recSum.Area()); // recDif.Area() 應為250 Console.WriteLine("rec1 - rec2 的面積: " + recDif.Area()); Console.ReadLine(); } } }
UsingOperOverload2.Rectangle(1/2) using System; namespace UsingOperOverload2 { class Rectangle { private int width; private int length; private int area; public Rectangle(int width, int length) { this.width = width; this.length = length; area = width * length; }
UsingOperOverload2.Rectangle(2/2) public int Area() {return area;} public static Rectangle operator +(Rectangle op1, Rectangle op2){ Rectangle result = new Rectangle( op1.width + op2.width, op1.length + op2.length); return result; } public static Rectangle operator -(Rectangle op1, Rectangle op2){ Rectangle result = new Rectangle( op1.width - op2.width, op1.length - op2.length); return result; } } }
運算子執行流程 Rectangle recSum = rec1 + rec2; public static Rectangle operator+(Rectangle op1, Rectangle op2){ Rectangle result = new Rectangle( op1.width + op2.width, op1.length + op2.length); return result; }
練習 • 撰寫測試主程式及類別Rational(有理數),其中須測試及定義有理數+、-、*、/、++運算子。可不必考慮約分。
RelOperOverload.Program(1/2) using System; namespace RelOperOverload { /* * 示範關聯運算子>和<的多載 * 4/11/2007 */ class Program { static void Main(string[] args) { StudentClass clsA = new StudentClass(20); StudentClass clsB = new StudentClass(30); bool clsAIsLarger = clsA > clsB; string message = clsAIsLarger ? "A班人數大於B班" : "A班人數不大於B班";
RelOperOverload.Program(2/2) Console.WriteLine(message); Console.ReadLine(); } } }
RelOperOverload.StudentClass(1/3) using System; namespace RelOperOverload { public class StudentClass { private int nStudents; public StudentClass(int nStudents) { if (nStudents < 0) { this.nStudents = 0; } else { this.nStudents = nStudents; } }
RelOperOverload.StudentClass(2/3) public int accessNStudents { get { return nStudents; } } public static bool operator >(StudentClass op1, StudentClass op2) { bool result = (op1.nStudents > op2.nStudents); return result; }
RelOperOverload.StudentClass(3/3) public static bool operator <(StudentClass op1, StudentClass op2) { bool result = (op1.nStudents < op2.nStudents); return result; } } }
練習 • 在類別Rational(有理數)中添加有理數>、<、!(檢驗是否為0)運算子,並予測試。 • 處理Rational(有理數)類別與整數進行+、-、*、/的情形
RelOperOverload2.Program(1/2) using System; namespace RelOperOverload2 { /* * 示範關聯運算子==,!=,Equals,GetHashCode等的多載 * 4/11/2007 */ class Program { static void Main(string[] args) { StudentClass clsA = new StudentClass("A", 20); StudentClass clsB = new StudentClass("B", 20); bool clsAEqualsclsB = clsA == clsB; string message = clsAEqualsclsB ? “clsA與clsB相等”: “clsA與clsB不等";
RelOperOverload2.Program(2/2) Console.WriteLine(message); clsAEqualsclsB = clsA.Equals(clsB); message = clsAEqualsclsB ? “clsA與clsB相等": “clsA與clsB不等"; Console.WriteLine(message); Console.ReadLine(); } } }
RelOperOverload2.StudentClass(1/3) using System; namespace RelOperOverload2 { public class StudentClass { private int nStudents; private string name; public StudentClass(string name, int nStudents) { this.name = name; if (nStudents < 0) { this.nStudents = 0; }
RelOperOverload2.StudentClass(2/3) else { this.nStudents = nStudents; } } public static bool operator ==(StudentClass op1, StudentClass op2) { bool result = ( op1.name.Equals(op2.name) ) && (op1.nStudents == op2.nStudents); return result; } public static bool operator !=(StudentClass op1, StudentClass op2) { return !(op1 == op2); }
RelOperOverload2.StudentClass(3/3) public override bool Equals(object obj) { bool result = false; if (obj is StudentClass){ StudentClass op = (StudentClass) obj; result = name.Equals(op.name) && (nStudents == op.nStudents); } return result; } public override int GetHashCode(){ return nStudents.GetHashCode() + name.GetHashCode(); } } }
ConvertOper.Program (1/2) using System; namespace ConvertOper { /* * 示範explicit與implicit的轉換 * 4/11/2007 */ class Program { static void Main(string[] args) { Rectangle rec = new Rectangle(15, 10); int area = (int) rec; Console.WriteLine("rec面積為" + area); Square sq = new Square(20);
ConvertOper.Program (2/2) rec = sq; area = (int)rec; Console.WriteLine("sq面積為" + area); Console.ReadLine(); } } }
ConvertOper.Rectangle (1/2) using System; namespace ConverOper { public class Rectangle { int width; int length; int area; public Rectangle(int width, int length) { this.width = width; this.length = length; area = length * width; }
ConvertOper.Rectangle (2/2) public static explicit operator int(Rectangle op) { return op.area; } } }
ConvertOper.Square using System; namespace ConvertOper { public class Square{ private int width; public Square(int width){ this.width = width; } public static implicit operator Rectangle( Square op ) { Rectangle rec = new Rectangle( op.width, op.width ); return rec; } } }
練習 • 在類別Rational(有理數)中添加有理數==、!=運算子及Equals、GetHashCode方法,並予測試。 • 在類別Rational(有理數)中添加轉為double的explicit運算子,及int轉為Rational的implicit運算子