在C#中,类是面向对象编程的基本概念之一。类是一种模板或蓝图,用于定义对象的属性和行为。它是创建对象的基础,包含数据成员(字段)和函数成员(方法)。通过定义类,可以创建多个具有相似属性和行为的对象。
类是面向对象编程中的基本概念之一,它是一种模板或蓝图,用于定义对象的属性和行为。类提供了一种组织和封装数据以及相关操作的方式,它将数据成员(字段)和函数成员(方法)封装在一起,形成一个独立的实体。
通过类,可以创建多个具有相似属性和行为的对象。对象是类的实例,它可以使用类中定义的数据和函数来执行特定的任务。类定义了对象的结构和行为,而对象则代表了类的具体实例。
继承是面向对象编程中的另一个重要概念,它允许一个类继承另一个类的属性和行为。被继承的类称为基类或父类,继承这个类的类称为派生类或子类。派生类可以继承基类的成员,并可以添加新的数据成员和函数成员,或者修改已继承的成员。
继承提供了代码重用和扩展的能力。通过继承,派生类可以使用基类已有的功能,避免了重复编写相似的代码。派生类可以通过添加新的成员来扩展基类的功能,也可以重写基类的成员来修改其行为。
继承支持多层次的层级关系,也就是派生类可以成为另一个派生类的基类,形成类的继承链。这种层级关系可以形成更复杂的类结构,并支持更高级别的抽象和组织。
除了基本的类和继承概念,面向对象编程还涉及其他概念,如抽象类、接口、多态等。这些概念进一步扩展了类和继承的能力,使代码更具灵活性、可扩展性和可维护性。它们提供了一种更高级别的代码组织和设计方法,使得面向对象编程更具优势和效率。
构造函数与析构函数
这段代码定义了一个名为Person
的类和一个Program
类。Person
类具有公共的整数Number
和字符串Name
属性,以及一个私有的整数tmp
字段。
在Person
类中,定义了一个构造函数和一个析构函数。构造函数用于初始化Person
类的实例,并将传入的参数赋值给相应的属性。析构函数在对象被销毁时执行,用于释放对象占用的资源。
在Program
类的Main
方法中,创建了一个Person
类的实例ptr
,并传入参数1001
和"lyshark"
给构造函数进行初始化。然后,使用ptr
对象访问其属性Number
和Name
,并将它们输出到控制台。
最后,通过Console.ReadKey()
等待用户按下任意键退出程序。
总体来说,这段代码演示了如何定义类和构造函数,以及如何创建类的实例并访问其属性。同时,也展示了析构函数的使用,用于在对象销毁时执行清理操作。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Person
{
public int Number;
public string Name;
private int tmp = 0;
// 定义构造函数
public Person(int x,string y)
{
this.Number = x;
this.Name = y;
Console.WriteLine("构造函数执行");
}
// 定义析构函数
~Person()
{
Console.WriteLine("析构函数执行");
}
}
class Program
{
static void Main(string[] args)
{
Person ptr = new Person(1001, "lyshark");
Console.WriteLine("ID: {0} Name: {1}", ptr.Number, ptr.Name);
Console.ReadKey();
}
}
}
对象中Get与Set方法
这段代码定义了一个名为Person
的类和一个Program
类。Person
类具有一个私有的整数_age
字段和一个公共的age
属性。
在age
属性中,定义了get
和set
方法。get
方法用于返回_age
字段的值,而set
方法用于接收用户赋值给属性的值,并进行一些逻辑判断。如果赋值的值小于0或大于100,则将属性的值设为0;否则,将赋值的值赋给_age
字段。
在Person
类的构造函数中,通过传入的参数将年龄赋值给age
属性。
在Program
类的Main
方法中,创建了一个Person
类的实例ptr
,并将年龄初始化为10。然后,通过访问ptr
对象的age
属性,输出其正常年龄。
接着,创建了另一个Person
类的实例ptr_err
,将年龄初始化为102,超出了合理的范围。再次通过访问ptr_err
对象的age
属性,输出其异常年龄。根据属性的设置逻辑,异常年龄将被设置为0。
最后,通过Console.ReadKey()
等待用户按下任意键退出程序。
总体来说,这段代码演示了如何定义属性,并在属性的set
方法中进行逻辑判断和限制。通过属性的使用,可以对属性的赋值和获取进行控制和验证。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Person
{
private int _age;
public int age
{
// 当用户输出该属性的值是执行Get方法
get { return _age; }
// 当用户对该属性赋值时执行Set方法
set
{
// 判断如果年龄小于0或者大于100则直接返回0
if (value < 0 || value > 100)
{
value = 0;
}
// 否则将用户数据赋值给变量
_age = value;
}
}
// 定义构造函数
public Person(int x)
{
this.age = x;
}
}
class Program
{
static void Main(string[] args)
{
Person ptr = new Person(10);
Console.WriteLine("正常年龄: {0}", ptr.age);
Person ptr_err = new Person(102);
Console.WriteLine("异常年龄: {0}", ptr_err.age);
Console.ReadKey();
}
}
}
静态方法与非静态方法
这段代码定义了一个名为Person
的类和一个Program
类。Person
类具有两个字段:一个私有的静态字符串_name
和一个私有的字符_gender
。同时,Person
类还定义了两个属性:一个公共的静态字符串属性Name
和一个公共的字符属性Gender
。
Name
属性使用Person._name
作为字段,用于获取和设置静态的名称。Gender
属性使用_gender
字段,用于获取和设置实例的性别。
Person
类还定义了两个方法:一个非静态的方法M1()
和一个静态的方法M2()
。M1()
方法输出"我是非静态的方法",而M2()
方法输出"我是一个静态方法"。
在Program
类的Main
方法中,创建了一个Person
类的实例ptr
。然后,通过调用ptr
对象的非静态方法M1()
,输出"我是非静态的方法"。接着,通过调用Person
类的静态方法M2()
,输出"我是一个静态方法"。
最后,通过Console.ReadKey()
等待用户按下任意键退出程序。
总体来说,这段代码演示了静态成员和实例成员的区别。静态成员属于类本身,可以通过类名直接访问;实例成员属于类的实例,需要通过实例对象来访问。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Person
{
private static string _name;
public static string Name
{
get { return Person._name; }
set { Person._name = value; }
}
private char _gender;
public char Gender
{
get { return _gender; }
set { _gender = value; }
}
public void M1()
{
Console.WriteLine("我是非静态的方法");
}
public static void M2()
{
Console.WriteLine("我是一个静态方法");
}
}
class Program
{
static void Main(string[] args)
{
Person ptr = new Person();
// 调用非静态方法
ptr.M1();
// 调用静态方法
Person.M2();
Console.ReadKey();
}
}
}
继承的基本使用
这段代码定义了一个基类Person
和一个派生类Student
。基类Person
具有两个公共字段name
和age
,以及一个构造函数Person(string _name, int _age)
和一个方法Display()
用于显示姓名和年龄。
派生类Student
继承了基类Person
,并添加了一个额外的字段stu
表示学生编号。派生类Student
还定义了一个与基类同名的方法Display()
,用于显示学生编号、姓名和年龄。
在Main
方法中,首先创建了一个基类Person
的实例ptr
,并调用Display()
方法显示姓名和年龄。然后创建了一个派生类Student
的实例stu
,并调用Display()
方法显示学生编号、姓名和年龄。
总结来说,这段代码演示了类的继承关系。派生类可以继承基类的字段、构造函数和方法,并且可以在派生类中添加额外的字段和方法。通过继承,派生类可以重用基类的代码,并且可以扩展和修改基类的功能。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
// 定义基类
public class Person
{
public string name;
public int age;
public Person(string _name, int _age)
{
this.name = _name;
this.age = _age;
}
public void Display()
{
Console.WriteLine("姓名: {0} 年龄:{1} ", this.name, this.age);
}
}
// 定义派生类
public class Studnet: Person
{
public int stu;
public Studnet(string _name,int _age,int _stu):base(_name,_age)
{
this.stu = _stu;
}
public void Display()
{
Console.WriteLine("Stu编号: {0} 学生姓名: {1} 年龄: {2}",this.stu,this.name,this.age);
}
}
class Program
{
static void Main(string[] args)
{
// 定义基类
Person ptr = new Person("lyshark",22);
ptr.Display();
// 定义派生类
Studnet stu = new Studnet("lyshark",22,1001);
stu.Display();
Console.ReadKey();
}
}
}
虚方法实现多态
这段代码演示了在继承关系中使用虚方法和重写方法的概念。
首先定义了一个基类Person
,它具有一个字段name
和一个构造函数Person(string name)
。基类还定义了一个虚方法SayHello()
,用于输出基类方法的信息。
然后定义了两个派生类Japanese
和Chinese
,它们都继承自基类Person
。派生类分别重写了基类的SayHello()
方法,以输出特定国家的信息。Japanese
重写后会先调用基类的SayHello()
方法,然后输出"日本人";Chinese
直接输出"中国人"。
在Main
方法中,首先创建了一个Japanese
类的实例jap
和一个Chinese
类的实例chi
,并分别调用它们的SayHello()
方法。接着创建了一个Person
类型的数组per
,其中包含了jap
和chi
两个对象。通过循环遍历数组,可以直接调用基类的SayHello()
方法或派生类重写的SayHello()
方法,实现对不同对象的多态调用。
总结来说,虚方法和重写方法是面向对象中实现多态性的关键概念。通过使用virtual
和override
关键字,可以在派生类中重写基类的方法,并且可以在运行时根据对象的实际类型调用适当的方法。这种灵活性使得代码可以更加可扩展和可维护,同时提高了代码的可读性和复用性。
using System;
using System.Collections;
namespace ConsoleApplication1
{
// 定义一个人类的基类
public class Person
{
public string name;
public Person(string name)
{
this.name = name;
}
public virtual void SayHello()
{
Console.WriteLine("基类方法");
}
}
// 定义日本人并继承人类,重写SayHello方法
public class Japanese : Person
{
public Japanese(string name) : base(name) { }
// 重写父类的SayHello
public override void SayHello()
{
base.SayHello();
Console.WriteLine("日本人");
}
}
// 定义中国并继承人类,重写SayHello方法
public class Chinese : Person
{
public Chinese(string name) : base(name) { }
// 重写父类的SayHello
public override void SayHello()
{
Console.WriteLine("中国人");
}
}
class Program
{
static void Main(string[] args)
{
// 普通的调用方式
Japanese jap = new Japanese("卡尔文");
jap.SayHello();
Chinese chi = new Chinese("韩梅梅");
chi.SayHello();
// 直接通过循环调用
Person[] per = { jap, chi };
for (int x = 0; x < per.Length; x++)
per[x].SayHello();
Console.ReadKey();
}
}
}
抽象类实现多态
抽象类和抽象方法是用于定义一组相关类的通用行为的机制。抽象类不能被实例化,只能作为其他类的基类,并且可以包含具体的方法和抽象方法。派生类必须重写抽象类中的所有抽象方法,提供具体的实现。抽象类和抽象方法的使用可以实现代码的模板化和代码重用,同时也可以确保派生类具有特定的行为。当父类中的方法不知道如何实现的时候,可以考虑将父类定义为抽象类,将方法定义为抽象方法。
首先定义了一个抽象类Shape
,其中包含一个抽象方法GetArea()
。抽象类用abstract
关键字修饰,其中的抽象方法没有具体的实现,只有方法的签名,即返回类型和参数列表。抽象方法必须在派生类中进行重写实现。
然后定义了一个派生类CirCle
,它继承自抽象类Shape
。派生类重写了基类的抽象方法GetArea()
,并提供具体的实现。在这个例子中,CirCle
类表示一个圆形,它有两个属性x
和y
,在重写的GetArea()
方法中计算并返回圆形的面积。
在Main
方法中,由于抽象类不能被实例化,所以创建了一个抽象类Shape
的引用sp
,并用派生类CirCle
的实例进行初始化。通过抽象类的引用,调用了重写后的GetArea()
方法,计算出了圆形的面积并将结果输出。
using System;
using System.Collections;
namespace ConsoleApplication1
{
// 定义一个抽象类,等待让子类重写
public abstract class Shape
{
public abstract double GetArea();
}
// 定义子类重写抽象类
public class CirCle:Shape
{
public double x;
public double y;
public CirCle(double x,double y)
{
this.x = x;
this.y = y;
}
public override double GetArea()
{
return this.x * this.y;
}
}
class Program
{
static void Main(string[] args)
{
// 抽象类不可实例化,只能实例化子类
Shape sp = new CirCle(12.5,20.8);
double ret = sp.GetArea();
Console.WriteLine("结果是: {0}", ret);
Console.ReadKey();
}
}
}
接口实现多态
接口是一种规范,用于定义一组相关类的公共行为。它只包含方法的声明,没有具体的实现。派生类实现接口时必须提供接口中声明的方法的具体实现。通过接口可以实现多态性,使得不同的类可以被视为具有相同的行为。接口的使用可以增加代码的灵活性和可扩展性。接口不允许有访问修饰符,方法自动设置为自动属性。
这段代码展示了接口的概念以及接口的实现。
首先定义了一个接口Person
,其中声明了一个方法Display()
。接口是一种合同或契约,定义了一组行为或功能的规范,但没有具体的实现。接口中的方法只有方法签名,没有方法体。
然后定义了两个派生类Student
和Teacher
,它们都实现了接口Person
。这意味着这两个派生类必须提供对接口中声明的方法Display()
的具体实现。
在Main
方法中,创建了一个接口类型的引用stu
和tea
,分别用派生类Student
和Teacher
的实例进行初始化。通过接口的引用,调用了实现了接口的方法Display()
,分别输出了"定义学生"和"定义老师"。
using System;
using System.Collections;
namespace ConsoleApplication1
{
// 定义一个接口,等待让子类重写
public interface Person
{
void Display();
}
// 定义派生类,继承于Person接口
public class Student:Person
{
public void Display()
{
Console.WriteLine("定义学生");
}
}
// 定义派生类
public class Teacher:Person
{
public void Display()
{
Console.WriteLine("定义老师");
}
}
class Program
{
static void Main(string[] args)
{
// 调用学生方法
Person stu = new Student();
stu.Display();
// 调用老师方法
Person tea = new Teacher();
tea.Display();
Console.ReadKey();
}
}
}