Interface
1. Object -> Person -> Employee/Client
1.1 Upcasting
Same upcasting from Employee/Client to Object, as Object is the base class.
将 Employee/Client 上传到 Object 也是一样,因为 Object 是基类。
1.2 Downcasting
这里把一个Employee类型传成Person类型了。这是行得通的。
但是一个Person类型不一定是一个Employee类型。以上代码错误!!
Object Person is NOT an object Employee!
Employee2 line is RUN-TIME error!!!
总结:无论咋样,父类或父类的实例在右边,子类或子类的实例不能在左边!!! 只能左父右子。
1.2.1 Solution
- Keyword as. No exception but attempt.
as就是一种强制转换类型的方式!!!
- Keyword is. IS it acceptable conversion?
checks if person is object type of Employee. If “yes” –converts to Employee and keep the result in the variable employee
is操作符用于检查一个表达式的类型是否与指定的类型兼容。
2. Constructor Management
2.1 创建大量构造方法->目的是overloading??
如果 Accountclass 要有大量的构造方法:
C# 提供了一种从一个构造函数调用另一个构造函数的方法:
public Account(string inName, string inAddress, decimal inBalance)
{
Name = inName; Address = inAddress; Balance = inBalance;
}
public Account(string inName, string inAddress):this (inName, inAddress, 0){}//0是默认值
public Account(string inName):this(string inName,"None!",0){}//"None!"和0是默认值
关键词 this 意味着 "该类中的另一个构造函数"。这意味着从构造函数到对象本身的值的实际转移只发生在一个方法中,其他构造函数方法只是对它进行调用。对构造函数的调用发生在构造函数方法的主体之前。
• create one "master" constructor which handles the most comprehensive method of constructing the object.
• make all the other constructor methods use this.
2.2 this.name = name
Consider “this” this:
在构造函数里对参数使用相同的名字,构造函数不会太喜欢哦。
We can avoid this by using “this”:
2.3 Constructors and Exceptions ??
To stop this to be “constructed” we can throw an exception:
2.4 以多个构造函数为例的整个代码:
class Person
{
string name;
string address;
decimal balance;
public Person(string name, string address, decimal balance)
{
this.name = name;
this.address = address;
this.balance = balance;
}
public Person(string name, string address):this(name,address,0){ }
public Person(string name) : this(name,"None!", 0) { }
public void Print()
{
Console.WriteLine($"name is {name},live in {address},{balance}");
}
}
class Program
{
static void Main(string[] args)
{
Person person = new Person("Sherry", "汤臣一品", 777);
person.Print();
}
}
3. Interface
3.1 实现格式
- 以I开头:
Coding convention -the name of an interface should start with the letter “I”.
public interface IAccount
{
void PayInFund(decimal amount);
bool WithdrawFunds(decimal amount);
decimal GetBalance();
}
- 接口里有什么?
• Methods, properties, events, static fields and constructors, delegates –all that can be defined • They don’t need to have implementation
- 方法、属性、事件、静态字段和构造函数、委托--所有这些都可以定义--它们不需要实现
public interface IMovable
{
const int minSpeed = 0;
static int maxSpeed = 100;
void Move();
string Name { get; set; }
delegate void MoveHandle(string name);
event MoveHandle OnMove;
}
3.2 access modifier
如果没有指定访问修饰符--默认为 public,因为接口定义了类所要实现的功能!这对常量变量和静态变量都有效--默认情况下,它们在类和结构体中都是私有的!接口中方法,默认访问权限也是public,并且不能修改。
static void Main(string[] args)
{
Console.WriteLine(IMovable.minSpeed)
}
因此,这将是对 IMovable 变量的有效调用.
- 默认为内部接口 - 将访问修饰符设置为公共接口,则所有接口都可访问
3.3 Implementation note
- 如果接口有私有方法和属性 , 默认情况下必须有实现 -,接口的静态方法也是如此:
public interface IMovable
{
const int minSpeed = 0;
static int maxSpeed = 100;
static double GetTime(double distance, double speed)
{
return distance/speed;
}
static int MaxSpeed
{
get=>maxSpeed;
set
{
if (value>0)
maxSpeed = value;
}
}
}
3.4 接口的实现
如果一个类实现了一个接口,就意味着接口中描述的每个方法都有相应的实现--该类必须包含接口中描述的所有方法的具体版本
public interface IAccount
{
bool PayInFund(decimal amount);
void WithdrawFunds(decimal amount);
decimal GetBalance();
}
public class CustomerAccount:IAccount
{
private decimal balance = 0;
public bool PayImFund(decimal amount)
{
if (balance < amount)
{
return false;
}
else
{
balance = balance + amount;
return true;
}
}
public void WithdrawFunds(decimal amount)
{
balance += amount;
}
public decimal GetBalance()
{
return balance;
}
}
如果类中没有实现接口中的所有方法,就会报错。
有了接口,我们就不再从 "类是什么 "的角度来考虑类,而是开始从 "能做什么 "的角度来考虑类。
- 使用接口设计的系统更容易扩展--我们不必更改所有使用接口的类,例如--当我们创建账户对象时,我们只需询问是否需要标准账户或婴儿账户。
3.4.1 Implementing Multiple Interfaces
一个类可以根据需要实现尽可能多的接口
public class BabyAccount:IAccount, IPrintToPaper{ ...
3.5 Designing with interfaces
a system creation process :
–Collect as much metadata as possible about the problem
–Identify classes that you will have to create to represent the components in the problem
–Identify the actions (methods) and the values (properties) that the components must provide
–Put these into interfaces for each of the components
–Decide how these values and actions are to be tested
–Implement the components and test them as you develop
系统创建过程:
-尽可能多地收集有关问题的元数据
-确定必须创建的类,以表示问题中的组件
-确定组件必须提供的操作(方法)和值(属性
-将这些内容放入每个组件的接口中
-决定如何测试这些值和操作
-在开发过程中实施组件并对其进行测试
3.6 接口实现的完整代码
using System;
interface Ibook
{
public string Name { get; set; }
public int Id { get; set; }
public double Price { get; set; }
public void discountPric(int discount) { }
}
class Book : Ibook
{
public string Name { get; set; }
public int Id { get; set; }
public double Price { get; set; }
public double discountPrice(double discount)
{
double finalprice = Price * discount;
return finalprice;
}
}
class Program
{
static void Main(string[] args)
{
Book book = new Book();
book.Name = "Harry Potter";
book.Id = 27;
book.Price = 99.4;
Console.WriteLine($"The book name is {book.Name},Id is {book.Id},final price is {book.discountPrice(0.8)}");
}
}