###### tags: `C#` # **C#實作課程-Lesson 4** # 列舉 enum # 類別的繼承 ## 基底類別(父類別) vs 衍生類別(子類別) 語法: 衍生類別:基底類別 ●衍生類別只能繼承1個基底類別 ●如果程式碼不複雜,可將基底類別與其衍生類別寫在同一個檔案(.cs) ```csharp= public enum LogTypeDef { SystemError,Error,Information } public class Log { public LogTypeDef LogType { get; set; } public string LogContent { get; set; } public DateTime LogTime { get; set; } public string MailAddr { get; set; } public void WriteLog() { if (this.LogType ==LogTypeDef.SystemError) Console.WriteLine($"send email to{MailAddr}"); Console.WriteLine(LogContent); } } public class dbLog:Log { public void WritLog() { Console.WriteLine(MailAddr); } } public class txtLog:Log { } ``` # override(複寫) vs method hiding(方法遮蔽) ●基底類別&衍生類別可使用相同名稱與參數的方法,分為下列兩種使用方式 override(複寫) ```csharp= public class Log { public LogTypeDef LogType { get; set; } public string LogContent { get; set; } public DateTime LogTime { get; set; } public string MailAddr="abcd@gmail.com"; public virtual void WriteLog()//父類別使用virtual關鍵字 { if (this.LogType == LogTypeDef.SystemError) Console.WriteLine($"send email to: {MailAddr}"); Console.WriteLine($"Base Log Show: {this.LogContent}"); } } public class dbLog : Log { public override void WriteLog()//子類別使用override關鍵字 { Console.WriteLine(MailAddr); } } ``` 執行下列相同程式碼差異: ```csharp= class Program { static void Main(string[] args) { Log log1 = new dbLog(); Log log2 = new txtLog(); log1.WriteLog(); log2.WriteLog(); Console.ReadLine(); } } ``` ![](https://i.imgur.com/6g6SQAq.png) ※基底類別可用來統整衍生類別,ex:List<T> ```csharp= static void Main(string[] args) { Log log1 = new dbLog(); Log log2 = new txtLog(); var logs = new List<Log>(); logs.Add(log1); logs.Add(log2); foreach (var item in logs) { item.WriteLog(); } Console.ReadLine(); } ``` 執行效果相同↓ ![](https://i.imgur.com/6g6SQAq.png) *********************************************** method hiding(方法遮蔽) ```csharp= public class Log { public LogTypeDef LogType { get; set; } public string LogContent { get; set; } public DateTime LogTime { get; set; } public string MailAddr { get; set; } public void WriteLog()//父類別無關鍵字 { if (this.LogType == LogTypeDef.SystemError) Console.WriteLine($"send email to{MailAddr}"); Console.WriteLine(this.LogContent); } } public class dbLog : Log { public new void WriteLog()//子類別使用new關鍵字,不寫也會視為父類別方法遮蔽 { Console.WriteLine(MailAddr); } ``` 執行下列程式碼差異: ```csharp= class Program { static void Main(string[] args) { Log log1 = new dbLog(); Log log2 = new txtLog(); log1.WriteLog(); log2.WriteLog(); Console.ReadLine(); } } ``` ![](https://i.imgur.com/aQn8EEi.png) # 介面 Interface ## 介面是一種類別,原則上僅有規格內容,不會有方法實作(類似公版的概念) ```csharp= public interface IPay { int Cal(int money); } ``` ### 說明: 1.介面的命名:原則上會在前面加上"I" ![](https://i.imgur.com/NeyAEKn.png) 2.介面定義好後,除非必要,否則不應該再修改 3.如果一個類別繼承了介面,就必須依照介面的規格去撰寫(包含方法名稱與參數) ※可避免例如共同開發時,各自撰寫方法、參數等等不一致 ```csharp= public class StoreA:IPay { public int Cal(int money) { if (money >= 5000) { return money; } return money + 100; } } ``` 4.一個Class可以繼承多個interface,使用","區隔,同時也可以繼承基底類別 ex: ```csharp= public class StoreA:IPay,IPay2,IPay3 { } ``` ex: ```csharp= public class StoreA:BClass,IPay,IPay2,IPay3 { } ``` 練習-interface實作 ```csharp= class Program { static void Main(string[] args) { var Customer1 = new Customer(); Customer1.StorePay = new StoreA(); Console.WriteLine(Customer1.StorePay.Cal(5000)); Console.ReadLine(); } } ``` ```csharp= public class Customer { public string Name { get; set; } public IPay StorePay { get; set; } } ``` 練習-interface建立(多種登入方式) ```csharp= class Program { static void Main(string[] args) { Console.WriteLine("Enter Login Type:(1:FB,2:LINE,3:Google)"); var authtype = Console.ReadLine(); var auth = new UserAuth(); switch (authtype) { case "1": auth.DoLogin(new FBLogin()); break; case "2": auth.DoLogin(new LineLogin()); break; case "3": auth.DoLogin(new GoogleLogin()); break; } Console.ReadLine(); } } ``` ```csharp= public class UserAuth { public void DoLogin(ILogin login) { login.Login(); } } ``` ```csharp= public interface ILogin { bool Login(); } ``` ```csharp= public class FBLogin : ILogin { public bool Login() { Console.WriteLine("Do FB Login"); return true; } } public class LineLogin : ILogin { public bool Login() { Console.WriteLine("Do Line Login"); return true; } } public class GoogleLogin : ILogin { public bool Login() { Console.WriteLine("Do Google Login"); return true; } } ``` # 純文字txt檔案輸出、寫入、複製 ## 輸出 ```csharp= Path.Combine() //將字串合併為路徑 ``` ```csharp= File.ReadAllText(string path) //讀取檔案的所有文字,回傳string ``` ```csharp= File.ReadAllLines(string path) //讀取檔案所有行,回傳string[] ``` 範例: ![](https://i.imgur.com/0sX3EhV.png) ```csharp= using System.IO; public class FileAccessDemo { public static void ReadFile() { string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt"); string text = File.ReadAllText(filepath); Console.WriteLine("Txt Contents:{0} !!!", text); Console.WriteLine("====================分隔線===================="); string[] lines = File.ReadAllLines(filepath); foreach (string line in lines) { Console.WriteLine("\t" + line); } Console.ReadLine(); } } ``` ```csharp= class Program { static void Main(string[] args) { FileAccessDemo.ReadFile(); Console.ReadLine(); } } ``` ![](https://i.imgur.com/96W8Yp6.png) - ## 寫入 ```csharp= File.AppendAllLines(string path,string[]);//將字串陣列內容加在路徑檔案內容後方,不會覆寫 ``` ![](https://i.imgur.com/9LAG5tB.png) ```csharp= File.WriteAllLines(string path,string[]); //將路徑檔案內容全部覆寫掉 ``` ![](https://i.imgur.com/vkasGxK.png) ```csharp= public static void Write() { string filepath= Path.Combine(@"C:\Users\User\Documents", "Demo.txt"); string[] lines = { "ABCDEFG", "HIJKLMN", "OPQRSTU", "VWXYZ" }; File.WriteAllLines(filepath, lines); File.AppendAllLines(filepath, lines); } ``` ```csharp= static void Main(string[] args) { FileAccessDemo.Write(); Console.ReadLine(); } ``` ## 複製 ```csharp= //將路徑1檔案複製到路徑2檔案 //如果路徑2檔案已經存在,預設為不能覆寫(false) File.Copy(string path1, string path2); ``` ![](https://i.imgur.com/Y0JmcyF.png) ```csharp= //將路徑1檔案複製到路徑2檔案 //如果路徑2檔案已經存在,可設定是否能覆寫(true:能覆寫 false:不能覆寫) File.Copy(string path1, string path2,bool overwrite); ``` ```csharp= public static void Copy() { string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt"); string targetfilepath= Path.Combine(@"C:\Users\User\Documents", "DemoCopy.txt"); File.Copy(filepath, targetfilepath, true);//可覆寫目標路徑檔案 File.Copy(filepath, targetfilepath, false);//不可覆寫,故執行會失敗 //設定不可覆寫仍要能執行的方法: //if (File.Exists(targetPath)) //{ // File.Delete(targetPath); //} //File.Copy(filePath, targetPath, false); } ``` ```csharp= static void Main(string[] args) { FileAccessDemo.Copy(); Console.ReadLine(); } ``` ## 使用FileInfo + StreamReader輸出 ```csharp= public class FileInfoAccess { public static void ReadFile() { string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt"); FileInfo myfile = new FileInfo(filepath); using (StreamReader sr= myfile.OpenText()) { var str = string.Empty; while ((str=sr.ReadLine())!=null) { Console.WriteLine(str); } } } } ``` ## 使用FileInfo + StreamWriter寫入 ```csharp= public static void Write() { string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt"); FileInfo myfile = new FileInfo(filepath); string[] lines = { "ABCDEFG", "HIJKLMN", "OPQRSTU", "VWXYZ" }; using (StreamWriter sw=myfile.CreateText()) //覆寫路徑檔案內容 { foreach (var item in lines) { sw.WriteLine(item); } } using (StreamWriter sw = myfile.AppendText()) //內容新增在路徑檔案後方 { foreach (var item in lines) { sw.WriteLine(item); } } } ``` ## 使用FileInfo複製 ```csharp= public static void Copy() { string filepath = Path.Combine(@"C:\Users\User\Documents", "Demo.txt"); string targetfilepath = Path.Combine(@"C:\Users\User\Documents", "DemoCopy.txt"); FileInfo File1 = new FileInfo(filepath); if (!File1.Exists) { return; } else { FileInfo File2 = new FileInfo(targetfilepath); if (File2.Exists) { File2.Delete(); } File1.CopyTo(targetfilepath); } } ```