继承

RTTI

RTTI

概念 RTTI(Run Time Type Identification)即通过运行时类型识别,程序能够使用基类的指针或引用来检查着这些指针或引用所指的对象的实际派生类型。

相关资源

C#高级编程(第11版) Professional C# 7 and .NET Core 2.0

For code comments and issues please check Professional C#'s GitHub Repository

Please check my blog csharp.christiannagel.com for additional information for topics covered in the book.

ObjectOrientation 章节中有介绍,

但是有些内容没有细讲, 比如纯虚函数的子类如何 在全局变量声明,如何在函数中定义,使用


c#

父类,子类

1.VirtualMethods


// fish tail, lungs
// humam limbs(arms and legs), lungs
// bird wings, lungs
// public abstract class Organisms
{
public Int32 age{get;} public virtual void GetAge()
{
WriteLine($"moves with {limbs}");
} public abstract void Move( ); } public class Human: Organisms
{
public Human()
: base() { } public override void Move( ) // must override
{
WriteLine($"Human: moves with legs (using limbs when baby age)");
} } public class Kingkong: Organisms
{
public Human()
: base() { } public override void Move( ) // must override
{
WriteLine($"Kingkong: moves with limbs");
} } public class Fish: Organisms
{
public Fish()
: base() { } public override void Move( ) // must override
{
WriteLine($"Fish: moves with wings and tail");
}
} public class Horse: Organisms //horse zebra
{
public Horse()
: base() { } public override void Move( ) // must override
{
WriteLine($"Horse: moves with legs");
}
}
using System;

namespace VirtualMethods
{
class Program
{
//var _obj = null; //var 无法在全局变量 声明
Organisms _Obj =null; static void Main()
{
var obj = new Human();
obj.age = 23;
obj.GetAge();
obj.Move(); }
static void Init()
{
_Obj = new Fish();
_Obj.age = 2;
_Obj.GetAge();
_Obj.Move();//父类有abstract function. 所有子类函数必须override,
} static void FuncA()
{
Fish fish = _Obj as Fish;//利用全局变量 _Obj
fish.age = 1;
fish.GetAge();
fish.Move();
} }
}

2.InheritanceWithConstructors

//Shape.cs
using System; namespace InheritanceWithConstructors
{
public class Position
{
public int X { get; set; }
public int Y { get; set; }
public override string ToString() => $"X: {X}, Y: {Y}";
} public class Size
{
public int Width { get; set; }
public int Height { get; set; }
public override string ToString() => $"Width: {Width}, Height: {Height}";
} public class Shape
{
public Shape(int width, int height, int x, int y)
{
Size = new Size { Width = width, Height = height };
Position = new Position { X = x, Y = y };
} public Position Position { get; }
public Size Size { get; } public virtual void Draw() => Console.WriteLine($"Shape with {Position} and {Size}"); public virtual void Move(Position newPosition)
{
Position.X = newPosition.X;
Position.Y = newPosition.Y;
Console.WriteLine($"moves to {Position}");
}
}
}
//ConcreteShapes.cs

using System;

namespace InheritanceWithConstructors
{
public class Rectangle : Shape
{
public Rectangle(int width, int height, int x, int y)
: base(width, height, x, y) { } public Rectangle()
: base(width: 0, height: 0, x: 0, y: 0) { } public override void Draw() =>
Console.WriteLine($"Rectangle with {Position} and {Size}"); public override void Move(Position newPosition)
{
Console.Write("Rectangle ");
base.Move(newPosition);
} public void PrintRectangleFuncA( )//只有Rectangle 才有的函数,其他类没有声明和实现
{
Console.Write("Rectangle FuncA ");
}
} public class Ellipse : Shape
{
public Ellipse(int width, int height, int x, int y)
: base(width, height, x, y) { } public Ellipse()
: base(width: 0, height: 0, x: 0, y: 0) { }
}
}
//Program.cs

namespace InheritanceWithConstructors
{
class Program
{
Shape _sharp = null;//全局变量
static void Main(string[] args)
{
var r = new Rectangle();
r.Position.X = 33;
r.Position.Y = 22;
r.Size.Width = 200;
r.Size.Height = 100;
r.Draw();
DrawShape(r); r.Move(new Position { X = 120, Y = 40 });
r.Draw(); Shape s1 = new Ellipse();
DrawShape(s1);
}
public staic void Init()
{
_sharp = new Rectangle();//如果_sharp 是全局变量, 让其他地方也可使用此对象 怎么办?
}
public staic void FuncA()
{
Rectangle rect= _sharp as Rectangle;
rect.PrintRectangleFuncA(); //只有Rectangle 才有的函数,其他类没有声明和实现,可以这样调用
} public static void DrawShape(Shape shape) => shape.Draw();
}
}

3.UsingInterfaces

//基本上和VirtualMethods 类似,但是所有接口类的 子类, 要通用, 子类必须

//IBankAccount.cs
namespace Wrox.ProCSharp
{
public interface IBankAccount
{
void PayIn(decimal amount);//子类必须有实现
bool Withdraw(decimal amount);//子类必须有实现
decimal Balance { get; }//子类必须有实现
}
}
//ITransferBankAccount.cs
namespace Wrox.ProCSharp
{
public interface ITransferBankAccount : IBankAccount
{
bool TransferTo(IBankAccount destination, decimal amount);
}
}
//JupiterBank.cs

using System;

namespace Wrox.ProCSharp.JupiterBank
{
public class GoldAccount : IBankAccount
{
private decimal _balance; public void PayIn(decimal amount) => _balance += amount; public bool Withdraw(decimal amount)//Withdraw撤回
{
if (_balance >= amount)
{
Console.WriteLine($"GoldAccount(IBankAccount): Withdraw(){_balance}");
_balance -= amount;
return true;
}
Console.WriteLine("GoldAccount(IBankAccount): Withdraw attempt failed.");
return false;
} public decimal Balance => _balance; public override string ToString() =>
$"GoldAccount(IBankAccount): Balance = {_balance,6:C}";
} public class CurrentAccount : ITransferBankAccount
{
private decimal _balance; public void PayIn(decimal amount) => _balance += amount; public bool Withdraw(decimal amount)
{
if (_balance >= amount)
{
_balance -= amount;
return true;
}
Console.WriteLine("Withdrawal attempt failed.");
return false;
} public decimal Balance => _balance; public bool TransferTo(IBankAccount destination, decimal amount)
{
bool result = Withdraw(amount);
if (result)
{
destination.PayIn(amount);
}
return result;
} public override string ToString() =>
$"Jupiter Bank Current Account: Balance = {_balance,6:C}";
}
}
//VenusBank.cs

using System;

namespace Wrox.ProCSharp.VenusBank
{
public class SaverAccount : IBankAccount
{
private decimal _balance; public void PayIn(decimal amount) => _balance += amount; public bool Withdraw(decimal amount)
{
if (_balance >= amount)
{
_balance -= amount;
return true;
}
Console.WriteLine("Withdrawal attempt failed.");
return false;
} public decimal Balance => _balance; public override string ToString() =>
$"Venus Bank Saver: Balance = {_balance,6:C}";
}
}
//Program.cs
namespace UsingInterfaces
{
class Program
{
IBankAccount _golbal_obj =null;//全局变量
static void Main()
{
IBankAccount venusAccount = new SaverAccount();
IBankAccount jupiterAccount = new GoldAccount(); venusAccount.PayIn(200);
venusAccount.Withdraw(100);
Console.WriteLine(venusAccount.ToString()); jupiterAccount.PayIn(500);
jupiterAccount.Withdraw(600);
jupiterAccount.Withdraw(100);
Console.WriteLine(jupiterAccount.ToString()); } public static void Init()
{
_golbal_obj = new SaverAccount();//用子类去new
} public static void FunA()
{
if(_golbal_obj!=null)
{
_golbal_obj.PayIn(100);//直接调用SaverAccount 子类的 实现,所以这也是为什么需要子类全部都要实现,
_golbal_obj.Withdraw(100);//直接调用SaverAccount 子类的 实现
}
} }
}

c# 面向对象/继承关系设计的更多相关文章

  1. OC面向对象继承关系和组合关系笔记

    继承关系是描述类和类之间的关系,两个类分别称为子类和父类,子类继承了父类,子类就拥有了父类的属性和方法: 继承的关系特点描述出来就是:** “是” **  (例如:学生类 是 人类) 组合关系描述的语 ...

  2. js面向对象继承

    前言 最近看到js面向对象这章节了,主要学习了原型和面向对象继承关系,为了梳理自己的知识逻辑,特此记录. js的面向对象 先说说我目前了解的js创建对象方法 1.写一个函数,然后通过new创建对象 2 ...

  3. 面向对象设计之------Is-A(继承关系)、Has-A(合成关系,组合关系)和Use-A(依赖关系)(转)

    原文url:http://blog.csdn.net/loveyou128144/article/details/4749576 @Is-A,Has-A,Use-A则是用来描述类与类之间关系的.简单的 ...

  4. 对象的继承关系在数据库中的实现方式和PowerDesigner设计

    原文:对象的继承关系在数据库中的实现方式和PowerDesigner设计 在面向对象的编程中,使用对象的继承是一个非常普遍的做法,但是在关系数据库管理系统RDBMS中,使用的是外键表示实体(表)之间的 ...

  5. Java实验项目三——编程实现Person类,学生类的设计及其继承关系

    Program: 编程实现Person类,学生类的设计及其继承关系 代码如下: 定义抽象类Person 1 /* 2 * Description:建立抽象类 3 * 4 * Written By:Ca ...

  6. JavaScript面向对象编程(9)高速构建继承关系之整合原型链

    前面我们铺垫了非常多细节.是为了让大家更加明晰prototype的使用细节: 如今能够将前面的知识整合起来,写一个函数用于高速构建基于原型链的继承关系了: function extend(Child, ...

  7. Java面向对象 继承(下)

     Java面向对象   继承(下) 知识概要:               (1)抽象类 1.1 抽象类概述                            1.2 抽象类的特点       ...

  8. day25 面向对象继承,多态,

    这两天所学的都是面向对象,后面还有几天也是它,面向对象主要有三个大的模块,封装,继承,多态,(组合),昨天主要讲了面向对象的命名空间,还有组合的用法,今天是讲的继承还有继承里面所包括的钻石继承,以及多 ...

  9. 游戏编程之Unity常用脚本类的继承关系

    前言学习Unity开发引擎的初学者会接触大量的脚本类,而这些类之间的关系往往容易被忽略.本文对Unity引擎开发中的一些常用类及其关系进行了简单的归纳总结. 博文首发地址:http://tieba.b ...

随机推荐

  1. CSPS模拟86-87

    模拟86 T1,烧水,按位统计贡献,利用某种sao操作避免数位dp #include<iostream> #include<cstdio> #include<cstrin ...

  2. 数据结构实验之图论三:判断可达性(SDUT 2138)(简单DFS)

    #include <bits/stdc++.h> using namespace std; int gra[1002][1005]; int vis[1002]; int n,m; voi ...

  3. spark map函数中使用println无法输出

    问题 // 每个点为hardData中的一个Array val hardData = spark.read.textFile(args(0)).rdd .map(_.split(" &quo ...

  4. Go 语言入门(二)方法和接口

    写在前面 在学习 Go 语言之前,我自己是有一定的 Java 和 C++ 基础的,这篇文章主要是基于A tour of Go编写的,主要是希望记录一下自己的学习历程,加深自己的理解 Go 语言入门(二 ...

  5. Fiddler is not capturing web request from Firefox

    Fiddler is not capturing web request from Firefox You can also get the FiddlerHook plug in for Firef ...

  6. 关于linux下的系统存储管理

    https://blog.csdn.net/aaaaaab_/article/details/80159871 //查看当前系统磁盘使用空间 df -h //查看当前目录文件占用空间大小 du -sh ...

  7. Linux | Vim使用

    Linux vi/vim 所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在. 但是目前我们使用比较多的是 vim 编辑器. vim 具有程序编辑的能力,可以主 ...

  8. cin中的注意事项

    猎豹网校C++ Primer学习笔记 - ostartech - 博客园 https://www.cnblogs.com/wxl845235800/p/11396323.html 在VS中使用cin& ...

  9. IDEA启动tomcat报错:java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext、ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component

    先看错误日志: -May- ::.M26 -May- :: :: UTC -May- ::29.845 信息 [main] org.apache.catalina.startup.VersionLog ...

  10. https://www.cnblogs.com/

    Linux如何查看端口 1.lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000 # lsof -i:8000 COMMAND PID USER ...