C# 抽象参数和方法初学者

C# 抽象参数和方法初学者,c#,inheritance,abstraction,C#,Inheritance,Abstraction,我只是在为我的编码课程做一些练习。我刚刚开始抽象,所以对我来说还是有点合拍。我已经得到了这段代码,到目前为止,我已经成功地为常规属性赋值。我想通过虚拟方法运行一个抽象属性,并最终将结果分配给该属性。抽象方法应该在第二个派生类而不是第一个派生类上重写 现在的结果是,两个派生类的BPM属性的值都是0,尽管我不知道为什么 public abstract class Music { protected string genre; protected int bpm; publi

我只是在为我的编码课程做一些练习。我刚刚开始抽象,所以对我来说还是有点合拍。我已经得到了这段代码,到目前为止,我已经成功地为常规属性赋值。我想通过虚拟方法运行一个抽象属性,并最终将结果分配给该属性。抽象方法应该在第二个派生类而不是第一个派生类上重写

现在的结果是,两个派生类的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;
    }
不是抽象属性。你现在看到的是一个。这是编译器为其创建隐藏备份字段的属性


第二,这里:

Console.WriteLine(t.Bpm + " " + d.Bpm);
您使用的是上述财产……而不是其他任何地方。它从未被赋值,因此它有其默认值,即0


你看,你有一个字段
protectedintbpm

    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#是区分大小写的


扩展答案 那么,我如何让“Bpm”和“Bpm”匹配,比如“流派”和“流派”匹配

您已经使用一个支持字段
流派
实现了
流派
属性:

    public string Genre //property
    {
        get
        {
            return genre;
        }
        set
        {
            genre = value;
        }
    }
这类似于编译器对
Bpm
所做的操作。唯一的区别是您无法访问
Bpm
备份字段


我会给你一个曲线球,告诉你你可以用你实现
Bpm
的方式来实现
Genre
,它会工作的。这就是你要做的:

  • 删除支持字段
    类型
  • 使
    流派
    自动实现:
    公共字符串流派{get;set;}
  • 让构造函数设置属性
    Genre=Genre
因此,您将看到您的代码更简单、更短。这就是自动实现属性的要点

因此,不,作为一个自动实现的属性并不会阻止
Bpm
工作。问题是您使用的字段
bpm
与此无关

您可以从构造函数写入属性,而不是写入无关字段,例如:

    public Music(string genre, int bpm)
    {
        Genre = genre; // Set Genre property
        Bpm = bpm; // Set Bpm property
    }

我想通过虚拟方法运行一个抽象属性,并最终将结果分配给该属性

如果我理解正确,您希望
Dubstep d=newdubstep(“Dubstep”,140)
将具有值为
80
Bpm
。对吧?

因此,我们希望所有写入都通过该方法。这就是你如何做到的:

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);
        }
    }
与此代码相同:

    public int Bpm
    {
        get => bpm;
        set => bpm = BPM(value);
    }
    public int Bpm
    {
        get
        {
            return bpm;
        }
        set
        {
            bpm = BPM(value);
        }
    }

写更少的代码只是一种简捷的方法……这让我很头疼,因为我得解释一下。看见不要让语法迷惑你。

Bpm
不是一个抽象属性(它不是声明的
abstract
);它是抽象类中的常规属性
public int Bpm{get;set;}
无关。@Llama噢!好的,我明白了。那么我想我在派生类中引用属性的方式也必须改变吗?谢谢你的帮助!那么我如何使
Bpm
Bpm
匹配,比如
Genre
Genre
匹配?或者它对常规属性和抽象属性有不同的作用吗?@Mike see extended answer.wow谢谢你!我昨天一整天都在复习课堂笔记,想弄明白这一点:)