C#中继承问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#中继承问题相关的知识,希望对你有一定的参考价值。

类之间的继承与接口之间的继承有区别嘛!
若有,则区别是什么

单继承机制,一个子类只能有一个父类
c#不允许一个一个子类有多个父类
c#允许接口多重继承,不允许类多重继承,所以在c#中实现两个或者两个以上继承,只能通过接口来实现,在c++中允许类多重继承
例子如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 继承

public interface Ishape

double Area();
double GramLength();
int Sides

get;



public interface IshapePlay

void Play();

public class Square : Ishape, IshapePlay

private int sides;
public int SideLength;
public Square()

sides = 4;

public int Sides

get

return sides;


public double Area()

return ((double)(SideLength * SideLength));


public double GramLength()

return ((double)(Sides * SideLength));

public void Play()

Console.WriteLine("\n计算正方形面积结果如下:");
Console.WriteLine("边长:0",this .SideLength );
Console.WriteLine("边数:0",this .Sides );
Console.WriteLine("面积:0",this .Area());



class Program

static void Main(string[] args)

Square sq = new Square();
sq.SideLength = 8;
sq.Play();



具有关键字abstract ,在实现内容上没有完全定义的类就叫抽象类。
抽象类和接口的区别如下:
① 在类来继承抽象类时,只需实现部分具体方法和全部抽象方法,而实现接口则要实现里面的全部方法。
②在接口中无成员变量,而抽象类中可有成员变量。
在Java中引进接口主要是为了解决多继承的问题。

1)接口中不能有非抽象方法,但抽象类中可以有。

2)一个类能实现多个接口,但只能有一个父类。

3)接口并不属于继承结构,它实际与继承无关,因此无关的类也可以实现同一个接口。

抽象类和方法
在我们所有乐器(Instrument)例子中,基础类Instrument内的方法都肯定是“伪”方法。若去调用这些方法,就会出现错误。那是由于Instrument的意图是为从它衍生出去的所有类都创建一个通用接口。
之所以要建立这个通用接口,唯一的原因就是它能为不同的子类型作出不同的表示。它为我们建立了一种基本形式,使我们能定义在所有衍生类里“通用”的一些东西。为阐述这个观念,另一个方法是把Instrument称为“抽象基础类”(简称“抽象类”)。若想通过该通用接口处理一系列类,就需要创建一个抽象类。对所有与基础类声明的签名相符的衍生类方法,都可以通过动态绑定机制进行调用(然而,正如上一节指出的那样,如果方法名与基础类相同,但自变量或参数不同,就会出现过载现象,那或许并非我们所愿意的)。
如果有一个象Instrument那样的抽象类,那个类的对象几乎肯定没有什么意义。换言之,Instrument的作用仅仅是表达接口,而不是表达一些具体的实施细节。所以创建一个Instrument对象是没有意义的,而且我们通常都应禁止用户那样做。为达到这个目的,可令Instrument内的所有方法都显示出错消息。但这样做会延迟信息到运行期,并要求在用户那一面进行彻底、可靠的测试。无论如何,最好的方法都是在编译期间捕捉到问题。
针对这个问题,Java专门提供了一种机制,名为“抽象方法”。它属于一种不完整的方法,只含有一个声明,没有方法主体。下面是抽象方法声明时采用的语法:
abstract void X();
包含了抽象方法的一个类叫作“抽象类”。如果一个类里包含了一个或多个抽象方法,类就必须指定成abstract(抽象)。否则,编译器会向我们报告一条出错消息。
若一个抽象类是不完整的,那么一旦有人试图生成那个类的一个对象,编译器又会采取什么行动呢?由于不能安全地为一个抽象类创建属于它的对象,所以会从编译器那里获得一条出错提示。通过这种方法,编译器可保证抽象类的“纯洁性”,我们不必担心会误用它。
如果从一个抽象类继承,而且想生成新类型的一个对象,就必须为基础类中的所有抽象方法提供方法定义。如果不这样做(完全可以选择不做),则衍生类也会是抽象的,而且编译器会强迫我们用abstract关键字标志那个类的“抽象”本质。
即使不包括任何abstract方法,亦可将一个类声明成“抽象类”。如果一个类没必要拥有任何抽象方法,而且我们想禁止那个类的所有实例,这种能力就会显得非常有用。
接口
“interface”(接口)关键字使抽象的概念更深入了一层。我们可将其想象为一个“纯”抽象类。它允许创建者规定一个类的基本形式:方法名、自变量列表以及返回类型,但不规定方法主体。接口也包含了基本数据类型的数据成员,但它们都默认为static和final。接口只提供一种形式,并不提供实施的细节。
接口这样描述自己:“对于实现我的所有类,看起来都应该象我现在这个样子”。因此,采用了一个特定接口的所有代码都知道对于那个接口可能会调用什么方法。这便是接口的全部含义。所以我们常把接口用于建立类和类之间的一个“协议”。有些面向对象的程序设计语言采用了一个名为“protocol”(协议)的关键字,它做的便是与接口相同的事情。
为创建一个接口,请使用interface关键字,而不要用class。与类相似,我们可在interface关键字的前面增加一个public关键字(但只有接口定义于同名的一个文件内);或者将其省略,营造一种“友好的”状态。
为了生成与一个特定的接口(或一组接口)相符的类,要使用implements(实现)关键字。我们要表达的意思是“接口看起来就象那个样子,这儿是它具体的工作细节”。除这些之外,我们其他的工作都与继承极为相似
参考技术A 1、构造函数不继承,派生类会自动调用基类构造函数。
2、若类内没有定义构造函数,系统会自动隐式生成一个不带参数的构造函数,比如定义一个类:
public class A


可以理解为它已经存在一个如下的构造函数

public class A

public A()




3、派生类构造函数自动调用基类的不带参数的构造函数,注意下面的格式
public class B:A

public B()




相当于
public class B:A

public B():base()





3、基类中带参数的构造函数必须显式调用,比如:
public class A

public A()



public A(string str)





public class B:A

public B():base("aaa")



参考技术B 问题如题吗?
好吧,答案也如题。

为啥我不能在 C# 中继承一个类? [复制]

【中文标题】为啥我不能在 C# 中继承一个类? [复制]【英文标题】:Why can't I inherit a class in c#? [duplicate]为什么我不能在 C# 中继承一个类? [复制] 【发布时间】:2019-08-10 09:47:07 【问题描述】:

我正在尝试创建一个基本的银行系统来练习使用类,在创建父类“Account”之后,我尝试创建一个“储蓄”类,它将作为子类并继承属性和方法,但是,无论我查找什么,都不会告诉我该怎么做。我收到诸如“必须声明一个主体,因为它没有标记为抽象、外部或部分”等错误。我真的不知道该怎么做才能让它工作,所以我希望这里有人可以提供帮助,这是我的代码:

public class Account

    protected string name;
    protected string birthdate;
    protected string address;
    protected double balance;
    protected string status;
    protected string type;

    public Account(string customerName, string customerBirthdate, string customerAddress, int customerBalance)
    
        name = customerName;
        birthdate = customerBirthdate;
        address = customerAddress;
        balance = customerBalance;
        status = "Ok";
        type = "Basic";         
    

    public void customerDetails()
    
        Console.WriteLine("Name: 0, Birthdate: 1, Address: 2", name, birthdate, address);
    

    public void accountDetails()
    
        Console.WriteLine("Balance: £0, Account Status: 1, Account Type: 2", Math.Round(balance, 2), status, type);
    

    private void updateStatus()
    
        if (balance < 0)
        
            status = "Overdrawn";
        
        else if (balance > 0 )
        
            status = "Ok";
        
    

    public void deposit(int amount)
    
        balance += amount;
        updateStatus();
    

    public void withdraw(int amount)
    
        balance -= amount;
        updateStatus();
    


public class Savings : Account

    public Savings(string customerName, string customerBirthdate, string customerAddress, int customerBalance) : Account(customerName, customerBirthdate, customerAddress, customerBalance)
    
        name = customerName;
        birthdate = customerBirthdate;
        address = customerAddress;
        balance = customerBalance;
        status = "Ok";
        type = "Basic";
    

如果有人可以帮助我,请提前感谢!

【问题讨论】:

当要调用基类的构造函数时,应使用base关键字,而不是基类本身的名称。 docs.microsoft.com/en-us/dotnet/csharp/tutorials/inheritance 和 tutorialspoint.com/csharp/csharp_inheritance.htm @JonathonChase 是对的,只需在 Savings 类中将 Account 类名称更改为 Base。 public Savings(string customerName, string customerBirthdate, string customerAddress, int customerBalance) : base(customerName, customerBirthdate, customerAddress, customerBalance) @JonathonChase 非常感谢大家,真不敢相信我错过了! 【参考方案1】:

代码应该是这样的(按基地更改帐户)

public class Account

    protected string name;
    protected string birthdate;
    protected string address;
    protected double balance;
    protected string status;
    protected string type;

    public Account(string customerName, string customerBirthdate, string customerAddress, int customerBalance)
    
        this.name = customerName;
        this.birthdate = customerBirthdate;
        this.address = customerAddress;
        this.balance = customerBalance;
        this.status = "Ok";
        this.type = "Basic";
    

    public void customerDetails()
    
        Console.WriteLine("Name: 0, Birthdate: 1, Address: 2", name, birthdate, address);
    

    public void accountDetails()
    
        Console.WriteLine("Balance: £0, Account Status: 1, Account Type: 2", Math.Round(balance, 2), status, type);
    

    private void updateStatus()
    
        if (balance < 0)
        
            status = "Overdrawn";
        
        else if (balance > 0)
        
            status = "Ok";
        
    

    public void deposit(int amount)
    
        balance += amount;
        updateStatus();
    

    public void withdraw(int amount)
    
        balance -= amount;
        updateStatus();
    


public class Savings : Account

    public Savings(string customerName, string customerBirthdate, string customerAddress, int customerBalance) : base (customerName, customerBirthdate, customerAddress, customerBalance)
    
        base.name = customerName;
        base.birthdate = customerBirthdate;
        base.address = customerAddress;
        base.balance = customerBalance;
        base.status = "Ok";
        base.type = "Basic";
    

【讨论】:

以上是关于C#中继承问题的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能在 C# 中继承一个类? [复制]

C#中继承对象的内存分配

在 C# 中继承泛型

如何在c#中继承非继承属性

C#中继承类为啥可以通过属性访问基类的私有字段。

在 SharpShell 从上下文菜单启动的程序中继承正确的 app.config