抽象参数和方法初学者
Abstract parameters and methods beginner
我只是在为我的编码课程做一些练习。我刚刚开始抽象,所以它对我来说仍然有点混乱。我有这段代码,到目前为止我已经设法为常规属性赋值。我想通过虚拟方法 运行 抽象 属性 并将结果分配给 属性 最后。抽象方法应该在第二个派生 class 而不是第一个
上被覆盖
现在的结果是两个派生的 classes 的 BPM 属性 的值为 0,但我不确定为什么。
public abstract class Music
{
protected string genre;
protected int bpm;
public string Genre //property
{
get
{
return genre;
}
set
{
genre = value;
}
}
public int Bpm //abstract property
{
get;
set;
}
public virtual int BPM(int b) //virtual method
{
this.bpm = b;
return b;
}
public Music(string genre, int bpm)
{
this.genre = genre;
this.bpm = BPM(bpm);
}
}
public class Techno : Music
{
public Techno(string genre, int bpm) : base(genre, bpm) { }
}
public class Dubstep : Music
{
public override int BPM(int b)
{
return base.BPM(b) / 2;
}
public Dubstep(string genre, int bpm) : base(genre,bpm) { }
}
//PROGRAM-------------------------------------------------------------
class Program
{
static void Main()
{
Techno t = new Techno("Techno", 130);
Dubstep d = new Dubstep("Dubstep", 140);
Console.WriteLine(t.Genre + " " + d.Genre);
Console.WriteLine(t.Bpm + " " + d.Bpm);
}
}
原答案
首先,这个:
public int Bpm //abstract property
{
get;
set;
}
不是摘要属性。您在这里看到的是 Auto-implemented property。这是一个 属性,编译器为其创建了一个隐藏的支持字段。
二、这里:
Console.WriteLine(t.Bpm + " " + d.Bpm);
你用上面提到的属性…其他地方都没有。它从来没有被赋值,所以它有它的默认值,恰好是0。
你看,你有一个字段 protected int bpm;
在你的方法中使用:
public virtual int BPM(int b) //virtual method
{
this.bpm = b;
return b;
}
你也在构造函数中设置了它:
public Music(string genre, int bpm)
{
this.genre = genre;
this.bpm = BPM(bpm);
}
但是那个字段和前面提到的属性没有任何关系。
重申 bpm
和 Bpm
是无关的。 我想我还应该提到 C# 区分大小写。
扩展答案
So how would I make 'Bpm' and 'bpm' match, like 'Genre' and 'genre' match?
您已经实现了 Genre
属性 和支持字段 genre
:
public string Genre //property
{
get
{
return genre;
}
set
{
genre = value;
}
}
这类似于编译器为 Bpm
所做的事情。唯一的区别是您无法访问 Bpm
支持字段。
我会抛给你一个曲线球,并说你可以按照你实现 Bpm
的方式实现 Genre
,它会起作用。这就是你要做的:
- 删除支持字段
genre
。
- 使
Genre
自动执行:public string Genre { get; set; }
。
- 让构造函数设置 属性
Genre = genre;
.
结果,您会发现您的代码更简单、更短。这就是自动实现属性的意义所在。
所以,不,作为一个自动实现的 属性 并不会阻止 Bpm
工作。问题是您使用的字段 bpm
与它无关。
您可以从构造函数写入 属性,而不是写入不相关的字段,例如:
public Music(string genre, int bpm)
{
Genre = genre; // Set Genre property
Bpm = bpm; // Set Bpm property
}
I want to run an abstract property through a virtual method and have the result assigned to the property finally
如果我没理解错的话,你希望 Dubstep d = new Dubstep("Dubstep", 140);
有 Bpm
,值为 80
。对吗?
所以,我们希望所有的写入都通过该方法。这就是你的做法:
public abstract class Music
{
private int bpm;
public Music(string genre, int bpm)
{
Genre = genre;
Bpm = bpm;
}
public int Bpm
{
get => bpm;
set => bpm = BPM(value);
}
public string Genre { get; set; }
public virtual int BPM(int b) //virtual method
{
return b;
}
}
此处,Bpm
不再自动执行。它将读取和写入字段 pbm
.
此外,流派是自动实现的。我这样做是因为我们不需要对它做任何特别的事情。
现在,每次设置 属性 时,都会 运行 bpm = BPM(value)
。这将调用 Dubstep
覆盖的虚拟方法,从而产生所需的行为。
要清楚,这段代码:
public int Bpm
{
get => bpm;
set => bpm = BPM(value);
}
与此代码相同:
public int Bpm
{
get
{
return bpm;
}
set
{
bpm = BPM(value);
}
}
这只是一种简写,可以少写代码……这让我很反感,因为我得解释一下。参见 Expression-bodied members (C# programming guide)。不要让语法混淆你。
我只是在为我的编码课程做一些练习。我刚刚开始抽象,所以它对我来说仍然有点混乱。我有这段代码,到目前为止我已经设法为常规属性赋值。我想通过虚拟方法 运行 抽象 属性 并将结果分配给 属性 最后。抽象方法应该在第二个派生 class 而不是第一个
上被覆盖现在的结果是两个派生的 classes 的 BPM 属性 的值为 0,但我不确定为什么。
public abstract class Music
{
protected string genre;
protected int bpm;
public string Genre //property
{
get
{
return genre;
}
set
{
genre = value;
}
}
public int Bpm //abstract property
{
get;
set;
}
public virtual int BPM(int b) //virtual method
{
this.bpm = b;
return b;
}
public Music(string genre, int bpm)
{
this.genre = genre;
this.bpm = BPM(bpm);
}
}
public class Techno : Music
{
public Techno(string genre, int bpm) : base(genre, bpm) { }
}
public class Dubstep : Music
{
public override int BPM(int b)
{
return base.BPM(b) / 2;
}
public Dubstep(string genre, int bpm) : base(genre,bpm) { }
}
//PROGRAM-------------------------------------------------------------
class Program
{
static void Main()
{
Techno t = new Techno("Techno", 130);
Dubstep d = new Dubstep("Dubstep", 140);
Console.WriteLine(t.Genre + " " + d.Genre);
Console.WriteLine(t.Bpm + " " + d.Bpm);
}
}
原答案
首先,这个:
public int Bpm //abstract property
{
get;
set;
}
不是摘要属性。您在这里看到的是 Auto-implemented property。这是一个 属性,编译器为其创建了一个隐藏的支持字段。
二、这里:
Console.WriteLine(t.Bpm + " " + d.Bpm);
你用上面提到的属性…其他地方都没有。它从来没有被赋值,所以它有它的默认值,恰好是0。
你看,你有一个字段 protected int bpm;
在你的方法中使用:
public virtual int BPM(int b) //virtual method
{
this.bpm = b;
return b;
}
你也在构造函数中设置了它:
public Music(string genre, int bpm)
{
this.genre = genre;
this.bpm = BPM(bpm);
}
但是那个字段和前面提到的属性没有任何关系。
重申 bpm
和 Bpm
是无关的。 我想我还应该提到 C# 区分大小写。
扩展答案
So how would I make 'Bpm' and 'bpm' match, like 'Genre' and 'genre' match?
您已经实现了 Genre
属性 和支持字段 genre
:
public string Genre //property
{
get
{
return genre;
}
set
{
genre = value;
}
}
这类似于编译器为 Bpm
所做的事情。唯一的区别是您无法访问 Bpm
支持字段。
我会抛给你一个曲线球,并说你可以按照你实现 Bpm
的方式实现 Genre
,它会起作用。这就是你要做的:
- 删除支持字段
genre
。 - 使
Genre
自动执行:public string Genre { get; set; }
。 - 让构造函数设置 属性
Genre = genre;
.
结果,您会发现您的代码更简单、更短。这就是自动实现属性的意义所在。
所以,不,作为一个自动实现的 属性 并不会阻止 Bpm
工作。问题是您使用的字段 bpm
与它无关。
您可以从构造函数写入 属性,而不是写入不相关的字段,例如:
public Music(string genre, int bpm)
{
Genre = genre; // Set Genre property
Bpm = bpm; // Set Bpm property
}
I want to run an abstract property through a virtual method and have the result assigned to the property finally
如果我没理解错的话,你希望 Dubstep d = new Dubstep("Dubstep", 140);
有 Bpm
,值为 80
。对吗?
所以,我们希望所有的写入都通过该方法。这就是你的做法:
public abstract class Music
{
private int bpm;
public Music(string genre, int bpm)
{
Genre = genre;
Bpm = bpm;
}
public int Bpm
{
get => bpm;
set => bpm = BPM(value);
}
public string Genre { get; set; }
public virtual int BPM(int b) //virtual method
{
return b;
}
}
此处,Bpm
不再自动执行。它将读取和写入字段 pbm
.
此外,流派是自动实现的。我这样做是因为我们不需要对它做任何特别的事情。
现在,每次设置 属性 时,都会 运行 bpm = BPM(value)
。这将调用 Dubstep
覆盖的虚拟方法,从而产生所需的行为。
要清楚,这段代码:
public int Bpm
{
get => bpm;
set => bpm = BPM(value);
}
与此代码相同:
public int Bpm
{
get
{
return bpm;
}
set
{
bpm = BPM(value);
}
}
这只是一种简写,可以少写代码……这让我很反感,因为我得解释一下。参见 Expression-bodied members (C# programming guide)。不要让语法混淆你。