个人理解:
在一些类中,写一些重复成员,我们可以将这些重复的成员,单独封装到一个类中,作为这些类的父类。
最终目的:解决类与类之间的代码冗余!!!
说明下:
在实际开发中,会把不同的类写到类文件中去,这里是为了演示方便写到一起了。
namespace ConsoleApp6 { class Program { static void Main(string[] args) { Son son = new Son(); // 之所以Son类可以访问到Person类的属性,因为Son类继承了Student类 // 而Student类继承了Person类,可以间接继承。 son.Age = 20; } } // Person类就是一个公共类、父类又叫基类 public class Person { private string _name; public string Name { get { return _name; } set { _name = value; } } private int _age; public int Age { get { return _age; } set { _age = value; } } } // Student类/派生类,继承了Person类 public class Student: Person { private int _height; public int Height { get { return _height; } set { _height = value; } } } // Son继承了Person类 public class Son: Student { } }
注意:
(1)子类不会继承父类的私有字段,因为访问不到!
(2)子类并没有继承父类的构造函数,但是,子类会默认先调用父类无参的构造函数,创建父类对象;之所以要先调用父类的无参构造函数,因为只有父类对象创建出来了,子类才能使用父类中的成员;
如果在父类中重写了一个有参数的构造函数,那么,那个无参的构造函数将会被干掉,子类就调用不了父类成员了,所以会导致子类报错!!!
解决办法:1> 在父类中手动的重新写一个无参数的构造函数 ( 在下边有对应例子 );
2> 在子类中显示的调用父类的构造函数,使用关键字 :base( )
下边例子中,子类继承父类,当new 子类时,父类无参构造函数会先执行,把父类创建出来,然后子类的构造函数,才会执行,这个也很容易理解,从思维逻辑上讲一点毛病都没有!
namespace ConsoleApp6 { class Program { static void Main(string[] args) { Student son = new Student(); } } public class Person { public Person() { Console.WriteLine("person"); Console.ReadKey(); } } public class Student: Person { public Student() { Console.WriteLine("student"); Console.ReadKey(); } } }对应上边解决方法一(在父类中在写一个无参的构造函数):
namespace ConsoleApp6 { class Program { static void Main(string[] args) { Student son = new Student(); } } public class Person { public string _name = "LVXINGCHEN"; public Person(string name) { Console.WriteLine("person"); Console.ReadKey(); } // 重新写一个无参的构造函数,此时,子类不会报错了,且当子类被调用时,父类对象将会被创建 public Person() { } } public class Student: Person { public Student() { Console.WriteLine("student"); Console.ReadKey(); } } }对应上边解决方法二(使用:base( ))
下边,我们对子类使用了 :base(), 来调用父类有参数的构造函数,从而创建父类对象。
输出结果:
namespace ConsoleApp6 { class Program { static void Main(string[] args) { Student stu = new Student("吕星辰", 20); } } public class Person { private string _name; public string Name { get { return _name; } set { _name = value; } } public Person(string name, int age) { // 在构造函数中访问本类的属性使用this this.Name = name; Console.WriteLine($"{name}, {age}"); Console.ReadKey(); } } public class Student: Person { public Student(string name, int age):base(name, age) { Console.WriteLine("student"); Console.ReadKey(); } } }
(1)继承的单根性:一个子类只能继承一个父类;
(2)继承的传递性:一个子类只能继承一个父类