我正在學習 c# 并且無法理解與實體相比繼承有哪些用例?
為了把它放在背景關系中,我正在制作一個控制臺 rpg,我目前的理解是我應該制作一個超類/基類npc,我從中繼承 3 個子類mage,paladin并且thief,我每個實體High level mage,low level mage.
它有意義還是我的邏輯有問題?在繼承/實體交換的情況下,這也會反過來作業嗎?
uj5u.com熱心網友回復:
將實體與繼承進行比較類似于比較蘋果和橙子。他們或多或少是不相關的。繼承用于定義類定義的層次結構,而實體是當您創建這些類之一的實際實體時。
一(但遠遠不是唯一的),你要問自己,若考慮繼承是正確的選擇是做子類和超類份額時,問題是一個關系?如果答案是肯定的,您可能想要使用繼承。如果答案是否定的,那么您幾乎肯定不會。
給大家舉幾個例子。
問:一個類是否與一個類Mercedes共享一個關系Car。
答:也許吧!更有可能的是,您只是擁有一個Car具有屬性的類Make(Model等等)。
問:一個MyWebPage份額是一個帶班的關系BaseWebPage
答:也許,是的。這是使用繼承的一種常見方式。MyWebPage覆寫基類的一些功能來控制渲染(作為一個例子)
回到你的例子。Class MageShare an是與Npc...的關系嗎?答案是另一個“Maybe”。為了使使用繼承有意義,您Mage必須覆寫的一些基本功能Npc- 您可能有類似Car上面的示例的內容。
uj5u.com熱心網友回復:
我不明白繼承的用例。這就是困擾我的原因
您對另一個答案發表了此評論;該答案討論了何時確定繼承的候選者,而 OneCricketeer 的答案討論了一個示例繼承層次結構,但您可能仍然想知道“有什么意義?”
從本質上講,關鍵是當您不在乎了解事物的詳細資訊時,它允許您以共同的方式對待事物。你不需要知道你手中的東西是刀、抹刀、信用卡等,以便能夠用它在三明治上涂抹蛋黃醬;我提到的所有這些東西都可以合理地用來舀起蛋黃醬并將其攤開。它們可以根據一些基本特性以通用方式進行處理,這些特性使它們成為良好的吊具(直邊、相當剛性的主體、防水和防油)
因此,假設您有自己的角色型別,并且它們都來自 NPC。假設每種玩家都有Health,當它達到 0 時,他們就死了。因為所有角色都有生命值,所以把它放在 NPC 上可能是有意義的。也許不同種類的角色有不同的起始生命值:
class Npc{
public int Health{get;set;}
}
class Medic:Npc{
Medic(){
Health = 30;
}
}
class Soldier:Npc{
Soldier(){
Health = 80;
}
}
假設你的玩家組織了一個部落/團隊/團隊,所以你的程式有:
var team = new Npc[10];
您的團隊中最多可以擁有 10 種角色,并且可以任意組合。繼承這個東西就是一個Soldier是一個Npc,一個Medic是一個Npc,所以現在你制作了一個Npc陣列,你可以在里面塞入士兵和醫生:
team[0] = new Soldier();
team[1] = new Medic();
假設有人向團隊投擲炸彈,它會對每個人的健康造成 55 點傷害。它會直接殺死一個新的醫生。我們不需要知道他們是什么樣的球員;所有 Npc 都有生命值,在這個通用的“從他們身上取一些生命值”場景中,醫生和士兵都可以被視為 Npc:
void DropBombOn(Npc[] team){
foreach(var npc in team) {
npc.Health -= 25;
if(npc.Health <= 0)
Console.WriteLine("Character is dead");
}
}
但是哪個角色已經死了?讓我們修改類:
class Npc{
public int Health{get;set;}
public string Name{get;set;}
}
設定它們:
team[0] = new Soldier("john");
team[1] = new Medic("fred");
class Medic:Npc{
Medic(string name){
Health = 30;
Name = name;
}
}
class Soldier:Npc{
Soldier(string name){
Health = 80;
Name = name;
}
}
void DropBombOn(Npc[] team){
foreach(var npc in team) {
npc.Health -= 55;
if(npc.Health <= 0)
Console.WriteLine("Character called " npc.Name " is dead");
}
}
你可以添加另一種型別的角色,他們仍然是一個 Npc,所以他們可以像其他所有角色一樣被轟炸..
Inheritance allows us to treat very specific types as something more general if there are operations that can take place in a general sense, on the general properties that all those kinds of things have.
Maybe all players have a bitmap image within their class that represents them. You can draw the team on screen by visiting each one and saying "give me your pixels"; you don't need to visit each one and say "if this npc is a medic, draw a medic. If this npc is a soldier draw a soldier.." - you just draw whatever pixels they give you and every different player gives different pixels. That, in essence is what we did with name - all characters have a name, we didn't care about which name we got; we just asked and printed out what we got
Another useful thing is that classes can have methods that override (replace) those on the base classes. Here we make a method that describes the character. We put it on the Npc, which means it will be available for anything that inherits from an Npc. We mark it abstract which means "anything that inherits from Npc must provide a method that does something, called DescribeYourself":
public class Npc{
public int Health{get;set;}
public string Name{get;set;}
public abstract void DescribeYourself();
}
public class Medic:Npc{
public Medic(string name){
Health = 30;
Name = name;
}
public override string DescribeYourself(){
return "I'm a medic called " Name;
}
}
public class Soldier:Npc{
public string ServiceNumber {get; set;}
public Soldier(string name,string serviceNumber){
Health = 80;
Name = name;
}
public override string DescribeYourself(){
return "I'm a soldier with service number " ServiceNumber " and I ain't telling you anything else";
}
}
void DropBombOn(Npc[] team){
foreach(var npc in team) {
npc.Health -= 55;
if(npc.Health <= 0)
Console.WriteLine(npc.DescribeYourself() " and I'm dead");
}
}
This time we didn't pull the name/print a common message - we asked the npc to describe itself. If it's a Soldier, the soldier version of the code runs and we see I'm a soldier with service number " ServiceNumber " and I ain't telling you anything else and I'm dead in the console. If it's a medic theyre a bit more forthcoming with info :)
We also have to provide a service number when we make a Soldier. This outlines that different kinds of classes can have different data requirements/more or less data during setup and use, but we can still treat them in a common way
The term for this "treat in a common way" is polymorphism and it's perhaps one of the most powerful things about C#.. In a practical sense, for example, Microsoft can provide a Stream class that, basically, writes bytes to somewhere, and then loads of inherited classes can write bytes to different places. We now have streams that can write bytes to.. the console, to a file, to some dropbox storage, to memory, to a string... And they're all used in the same way and the person calling write doesn't care how many hoops the code has to jump through to write to console vs file vs FTP server.. They just call Write with the expectation that the bytes will end up in the place promised. You can write you own streams, and hand them to Microsoft's classes - Microsoft's classes knew nothing關于你的類,但你仍然可以要求一個位圖將自己保存到你的流中,也許你的流類接受它并將位元組添加到電子郵件中并發送它......突然間你可以讓位圖自己寫入電子郵件和位圖可以完全不知道電子郵件是什么,但它仍然可以寫入。你可以完全不知道塞尺是什么,但你可以用它來傳播蛋黃醬。
uj5u.com熱心網友回復:
默認情況下,所有類都繼承自Object
為了使用非抽象類(或任何繼承的類),您需要創建一個實體。
實體保存欄位并定義函式,這些函式可以充當存盤在該實體中的其他實體的包裝器/訪問器(稱為組合)。
對于給定的示例,假設 NPC 具有級別。然后所有子類都從它擴展,因此繼承了它的屬性。法師(和其他型別)有自己的屬性
class NPC {
int Level { get; set; }
public NPC(int level) {
Level = level;
}
}
class Mage : NPC {
String PrimaryMagic {get; set; }
public Mage(int level, string magic) : base(level) {
PrimaryMagic = magic;
}
}
var lowMage = new Mage(1, "fire");
var highMage = new Mage(50, "ultima");
但是你也可以制作一個沒有特定屬性的通用等級角色
var nobody = new NPC(0);
您還可以取消 Mage 類并為所有 NPC 提供一些Spells串列屬性,例如默認為空/空。
var magicStudent = new NPC(1); // starts with no magic
// .. Game progresses
if (magicStudent.Level >= 5) {
magicStudent.Spells.Add("cure"); // Based on some condition, update a list of spells.
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/353481.html
