我目前正在開發一個代碼庫,并努力尋找一個最佳且干凈的解決方案。我已經洗掉了問題的背景關系以幫助將其簡化為它的根組件。該Scale屬性是對實際代碼庫中類的更復雜狀態的簡化。對于如何解決這個問題,我有一個想法(我將在底部參考) - 但是解決方案感覺很混亂,只是避開了我想要更好地理解的區域。
類層次結構
public class GreatGrandparent
{
public virtual int Scale { get; set; } = 1;
public virtual int GetTrueScale()
{
return Scale;
}
}
public class Grandparent : GreatGrandparent
{
public override int Scale { get; set; } = 2;
public override int GetTrueScale()
{
return Scale * base.GetTrueScale();
}
}
public class Parent : Grandparent
{
public override int Scale { get; set; } = 8;
}
public class Child : Parent
{
public override int Scale { get; set; } = 4;
}
代碼中的其他地方:
public class Main
{
Child aChild = new Child();
int aChildTrueScale = aChild.GetTrueScale();
}
- 預期結果:
4(4×1)(參考編輯1) - 實際結果:
16(4×4) - 期望的結果:
64(4×8×2×1)
我希望一個孩子通過從父母那里獲取所有比例因素來找到它的相對比例,這樣就可以了:
child relative scale = child scale × parent scale × … × base class scale
How can I (if possible) define the GetTrueScale method once in the parent class to get the desired result - which all children inherit - to avoid continuously overriding the method with duplicate implementations (the exception being the GreatGrandparent).
"Messy" Solution
Define a separate property/field in each class, and continuously override the aChildTrueScale() method with a return of ClassScale * base.GetTrueScale() where the ClassScale is a different property on each Class.
Edit 1
The expected result was my initial expectation based on my understanding at the time - thinking that within a base call the Scale reference would respect the change in scope change value to match that of the base class. With some further testing it appears that regardless of what scope when a base method is called, the referenced Scale value is always from the initial objects scope (hence 4*4).
Is it possible to refer to properties based on their scope? So in a base.GetTrueScale() call, any references within that function call will be on the base scope. Or am I completely missing something/trying to over simplify children?
Footnote
I've got a a bit of experience with procedural programming around data science, however I'm fairly inexperienced with object-oriented programming so forgive me if I'm ignorant to some core concepts. I’m happy to help clarify anything, thanks for taking the time to look over my first question! ^-^
(If anyone can think of a better title please let me know and I'll fix it up - was struggling to define the issue simply)
uj5u.com熱心網友回復:
我建議使用型別系統來建模這個層次結構是一個錯誤。你想要Child, Parent,GrandParent成為獨立的事物。這并不is-a表示您通常在型別系統中期望的關系。
所以改為:
public class Thingy {
public int Scale {get;set;}
public Thingy Parent {get;set;}
public int GetTrueScale()
{
var current = this;
var accumulator = current.Scale;
current = current.Parent;
while(current!=null)
{
accumulator = accumulator * current.Scale;
current = current.Parent;
}
return accumulator;
}
}
然后創建每個物件:
var greatGrandParent = new Thingy {Scale = 1};
var grandParent = new Thingy {Scale = 2, Parent = greatGrandParent};
var parent = new Thingy {Scale = 8, Parent = grandParent};
var child = new Thingy { Scale = 4, Parent = parent};
您現在可以呼叫child.GetTrueScale()并考慮層次結構的所有級別。
添加Children集合Thingy和其他更有趣的行為留作練習。
ThingyIThingy如果不同的級別確實需要單獨的型別,它本身也可以是一個介面。
uj5u.com熱心網友回復:
從評論中的討論來看,事實證明您不需要您的Scale屬性是可設定的(它的值在構造上是固定的),您甚至不需要它是虛擬的。您可以在類上只擁有一個屬性GreatGrandfather,如下所示:
public class GreatGrandparent
{
public int Scale { get; }
public GreatGrandparent(int scale)
{
Scale = scale;
}
}
public class Grandparent : GreatGrandparent
{
public Grandparent(int scale) : base(scale * 2) { }
}
public class Parent : Grandparent
{
public Parent(int scale) : base(scale * 8) { }
}
public class Child : Parent
{
public Child(int scale) : base(scale * 4) { }
}
在您的實際代碼中,您正在處理一個HashSet. 你可以寫這樣的東西,每個孩子都向 GreatGrandparent's 添加新專案HashSet:
public class GreatGrandparent
{
protected HashSet<string> hashSet = new();
public GreatGrandparent()
{
hashSet.Add("itemOne");
}
}
public class Grandparent : GreatGrandparent
{
public Grandparent()
{
hashSet.Add("itemTwo");
}
}
或者傳遞要添加到建構式鏈中的專案(更昂貴,但可能更整潔?):
public class GreatGrandparent
{
protected HashSet<string> hashSet;
public GreatGrandparent(IEnumerable<string> items)
{
hashSet = new(items);
hashSet.Add("itemOne");
}
}
public class Grandparent : GreatGrandparent
{
public Grandparent(IEnumerable<string> items) : base(items.Concat(new[] { "itemTwo" })) { }
}
uj5u.com熱心網友回復:
型別層次結構將按從 開始的順序呼叫most base type -> most derived。
由于您沒有重寫方法,Parent因此您Scale的方法不會成倍增加。這是你得到的一個原因16。最好除錯并查看代碼的執行順序。
您可以添加GetTrueScale()類的覆寫方法Parent以獲得所需的值64。整個代碼將如下所示:
public class GreatGrandparent
{
public virtual int Scale { get; set; } = 1;
public virtual int GetTrueScale()
{
Console.WriteLine("GreatGrandparent: " Scale);
return Scale;
}
}
public class Grandparent : GreatGrandparent
{
public override int Scale { get; set; } = 2;
public override int GetTrueScale()
{
Console.WriteLine("Grandparent: " Scale);
return Scale * base.GetTrueScale();
}
}
public class Parent : Grandparent
{
public override int Scale { get; set; } = 8;
public override int GetTrueScale()
{
Console.WriteLine("Grandparent: " Scale);
return Scale * base.GetTrueScale();
}
}
和Child類:
public class Child : Parent
{
public override int Scale { get; set; } = 4;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/454382.html
標籤:c# oop inheritance
上一篇:如何避免多載方法的多重定義
