网站首页 > 技术文章 正文
类,实例化与对象:类是某种事物的模板,是一种抽象化的概述;对象是根据此模板实例化的一个具体事物
类使用关键字class进行定义,对象通过关键字new实例化后产生;一般一个类使用一个.cs文件,类的访问修饰符决定类与其成员在外部被访问的权限级别(暂不涉及特殊类)
//public 访问修饰符的一种,外部任何地方都可以访问此类
//class 定义类的关键字
//Myclass 类名(强制遵守命名规则,非强制符合命名规范)
//类名一般都是大写(命名规范)
public class MyClass
{
//类的成员
}
类的成员暂时只说:字段,属性,构造方法与普通方法
1)字段:代表的是类的最根本的性质;一般为是私有的,只有类本身能调用(在类内部使用)
//private 访问修饰符 被修饰的字段表示是私有,外部访问不到
//int 表示这个字段的数据类型
//age 字段名称
private int age;//以分号结尾
2)属性:一般由get,set两个方法组成;属性名与字段名相同只是需要首字母大写,一般由public进行修饰;作用:控制(或约束)字段的取值与赋值
//属性类别包括:自动属性,只读属性,只写属性,可读可写属性
public int Age{get;set;}//自动属性
//普通成员变量;与属性区分开
//最好不要与属性重名
public double Height;
//只读属性:外部只能读取这个属性的值,无法进行赋值
public int Age
{
get { return age; }
}
//只读与只写属性不能并有,自己测试VS会给出报错信息
public int Age
{
//只写属性:外部只能为此属性赋值
//外部无法读取此属性的值
//value 接收外部的赋值
set { age = value; }
}
public int Age
{
//可读可写属性:外部既能赋值也能其值
get { return age; }
set { age = value; }
}
3)构造方法:与类名相同一般由public进行修饰;如果不写有一个默认的无参构造方法,如果写了,就会覆盖掉默认的无参构造方法;作用:在实例化对象时为公有属性进行赋值
public Myclass(int _age)
{
//this代表当前 类 Myclass
//this.Age 代表当前类中Age属性
//_age 接收实例化对象时传入的值
this.Age = _age;
}
//构造方法重载
public Myclass(int _age,string _name)
{
this.Age = _age;
this.Name=_name;
}
//还可以使用this书写构造方法的重载(构造方法间的调用)
//相当于调用了public Myclass(int _age)
//这个构造方法为_age进行赋值,减少代码量
public Myclass(int _age, string _name):this(_age)
{
// this.Age = _age;
this.Name = _name;
}
4)普通方法:由访问修饰符(没有,默认为private),返回值类型,方法名构成
//如果此方法供类的外部使用一般为public
//如果此方法供类的内部使用一般为private
//void 表示没有返回值
//方法名一般也是首字母大写
public void SayHi(int age)
{
Console.WriteLine("张三,今年{0}岁了",age);
}
实例化类的对象,调用类的公有属性与方法
static void Main(string[] args)
{
//实例化对象并为属性赋初始值
//赋初始值相当于调用类的构造方法
//new的作用
//1)实例化对象
//2)在内存中开辟对象所需的空间
//3)调用对象的构造方法
Myclass ms1 = new Myclass(18);
Myclass ms2 = new Myclass(18,"张三");
//调用类的普通方法
ms1.SayHi(20);
Console.ReadKey();
}
面向对象的三大特性:封装,继承,多态
1 封装的体现:如被类封装的成员,通过访问修饰符约束外部访问此成员的级别;字段封装为属性,相关的方法封装在一起等,最终目的是减少内部的暴露对外提供统一的访问接口
访问修饰符:设置被修饰的类或其成员的访问级别(使用权限)
private 当前类中可以访问,类中成员的默认访问修饰符。
protected 当前类及子类中可以访问(在继承中用)
internal 当前程序集内部可以访问(类的默认访问修饰符)
protected internal 当前程序集或子类中(不同程序集也可以访问,相当于两者的并集)
public 在任何地方都可以被访问
只有报错信息为:“可访问性不一致”的错误,基本就是因为使用者与被使用者之间的级别不对等,一般是使用者的级别低于被使用者,解决方法提高使用者的级别至对等或高于被使用者
//如子类的可访问级别比父类的高
//默认 internal
class Person
{ }
public class Student : Person
{
//父类Person 比 子类Student 的级别低
}
//其他情况之前说过不再赘述
2 继承是指类与类之间的关系;所有的类都继承Object类(相当于祖宗类)继承中基类与派生类相当于父类与子类
继承中有两大特性:
2.1)单根性:只有一个父类;使用接口可以实现多继承,两者区别:父类只能有一个(类比亲爹)只能写在子类的第一个位置;接口可以有多个(类比干爹)
2.2)传递性:子类的子类可以继承子类父类中的成员;相当于孙子可以继承爷爷的家产,但是孙子不是直接继承自爷爷而是通过父亲继承了爷爷的家产;因为在继承中只有子类继承父类的关系,没有子类继承爷类的关系,只是通过中间的父类达到了孙子继承爷爷的目的,从而实现类的传递性
使用继承的益处:1)代码重用 2)实现多态(使用了里氏替换原则LSP)便于后期的拓展与维护等
//父类
public class A
{
public int Age{ get; set; }
}
//子类
public class B:A
{
public string Name{ get; set; }
}
//A,B类自带无参数的构造方法
//实例化B的对象 B相当于有两个自动属性
//通过对象初始化器进行赋值
B b1=new B(){ Name = "张三", Age = 18 };
继承中的构造方法无法被继承,因此子类想要使用父类的构造方法时需要通过base关键字进行指定;可以使用this调用类内部自己其他的构造方法(构造方法的重载)
public class A
{
//一个参数
public A(int _age)
{
this.Age = _age;
}
//两个参数(只为演示this用法与下面B的构造方法无关)
public A(int _age, char _gender)
:this(_age)
{
this.Gender=_gender;
}
public int Age { get; set; }
public char Gender { get; set; }
}
public class B : A
{
//此类 不需要Gender属性
public B(int _age, string _name)
: base(_age)//调用了父亲的这个构造方法
{
//B中省略下面Age的赋值
//this.Age = _age;
this.Name = _name;
//它们的调用过程可通过调试查看
}
public string Name { get; set; }
}
//实例化B的对象
static void Main(string[] args)
{
B b1 = new B(18, "张三");
//在24代码这设置断点,通过逐语句进行调试,之前说过不再赘述
}
3 实现多态的三种方式:虚方法,抽象方法,接口
实现多态的目的:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化
3.1 虚方法:如果父类的某些方法需要在子类中进行重写,可使用virtual进行标记,继承的子类可使用override进行重写继承下的方法,虚方法不是必须要重写的方法
class Program
{
static void Main(string[] args)
{
Person p1 = new Person();
p1.SayHi();
Console.WriteLine("");
Person p2 = new Student();
//对虚方法进行了重写,因此调用子类重写后的方法
//相当于子类调用了自己的方法
p2.SayHi();
Console.WriteLine("");
//对虚方法没有进行重写,
//相当于父类调用了自己的方法
Person p3 = new Teacher();
p3.SayHi();
Console.WriteLine("");
//子类调用自己的方法
Teacher t1 = new Teacher();
t1.SayHi();
Console.ReadKey();
}
}
public class Person
{
//标记为虚方法
public virtual void SayHi()
{
Console.WriteLine("此方法已被 virtual 标记为虚方法,子类可重新");
}
}
public class Student : Person
{
public override void SayHi()
{
Console.WriteLine("重写了父类中的重名的虚方法");
}
}
public class Teacher : Person
{
//没有重写重名的方法最后加上new
//在子类中用new修饰一个方法的目的
//就是在子类中用该方法隐藏父类中对应的重名方法
//这样对同一个方法而言用父类的实例对像来调用
//和用子类的实例对象来调用就各不相同
//实现了在子类中用子类方法隐藏父类的方法。
public new void SayHi()
{
Console.WriteLine("隐藏了父类的同名方法");
}
}
3.2 抽象类与抽象方法:使用abstract进行标记,抽象方法只能定义在抽象类中,抽象方法没有方法体,不能进行实例化,只能实例化为子类;属于光说不做,只能由后代的某个子类必须重写;
public abstract class T
{
//抽象方法没有方法体
public abstract void Eat();
public abstract void Drink();
}
public abstract class T1 : T
{
//继承了父类的Eat()与Drink()方法
//只实现了Eat()方法
public override void Eat()
{
Console.WriteLine("实现了 T 中的Eat()方法");
}
//自己又添加一个抽象方法
public abstract void Sleep();
//因为Sleep()是抽象方法,因此 T1 必须是 抽象类
//如果没有此抽象方法 T1 就是普通类
//由子类T2统一实现继承下来的Drink()与Sleep()抽象方法
}
public class T2 : T1
{
public override void Drink()
{
Console.WriteLine("实现了 T1 的 Drink()方法 ");
}
public override void Sleep()
{
Console.WriteLine("实现了 T1 的 Sleep()方法 ");
}
//又重新实现了 T 中的方法
//会覆盖掉 T1 中实现方法的内容
public override void Eat()
{
Console.WriteLine("重新实现了 T 的 Eat()方法");
}
}
//实例化子类
class Program
{
static void Main(string[] args)
{
T test1 = new T2();
test1.Eat();
test1.Drink();
Console.WriteLine("");
T1 test2 = new T2();
test2.Eat();
test2.Drink();
test2.Sleep();
Console.WriteLine("");
T2 test3 = new T2();
test3.Eat();
test3.Drink();
test2.Sleep();
Console.ReadKey();
}
}
1)T1又添加了抽象方法,因此T1必须是抽象类
2)抽象方法的实现以最后实现的内容为准,相当于覆盖掉了之前实现的内容
虚方法与抽象方法的区别:
1)虚方法可以所在的类可以被实例化,也可以放在普通类,抽象类中
抽象类本身不能被实例化,只能实例化其子类,抽象方法只能定义在抽象类中
2)虚方法有方法体,在父类中必须进行实现,哪怕是空实现(方法体中没有代码)子类可以重写也可以不重写,没有强制性
抽象方法没有方法体,在父类中不能进行实现只能由子类进行实现(除非子类也是抽象类),继承的后辈子类只要没有进行实现,此抽象方法将一直具有强制性
3)不管是虚方法还是抽象方法都不能使用private进行修饰,因为这两种方法本身就是让其子类进行重写的,如果可以设置为private就失去了这些方法本身存在的意义
3.3 接口:使用interface进行定义,用于定义具有各种功能的方法,是一种能力,没有具体实现,与抽象方法一样都属于“光说不做”的类型
1)接口不能被实例化,只能实例化子类,接口中的方法也没有方法体
2)接口中只能有方法(方法,属性,索引器,事件)不能有字段,也没有修饰符(默认public)
3)可以实现多继承,同时解决类继承后体积庞大的问题,在实现接口的子类中必须全部实现接口中的方法,接口方法不能使用override,直接书写实现方法即可
4)实现方式:1)实现接口与显示实现接口其区别1)解决了方法重名的问题2)显示实现接口只能通过接口进行调用,子类调用不到
示例:麻雀与鹦鹉,继承一个父类同时实现了其他接口;提取父类(Bird)包含Show()方法;提取飞的能力(接口)与说话的能力(接口)
public class Bird
{
//子类可以重写
public virtual void Show()
{
Console.WriteLine("有翅膀会吃东西");
}
}
public interface IFlyable
{
//隐式public
void Fly();
}
public interface ISayable
{
void SayHi();
}
public class MQ : Bird, IFlyable
{
public override void Show()
{
//调用父类的虚方法
base.Show();
}
//实现接口,不能使用override
public void Fly()
{
Console.WriteLine("麻雀在飞");
}
}
//多继承时 父类在第一个,接口在后面
public class YW : Bird, ISayable, IFlyable
{
public override void Show()
{
//重写了父类的方法
Console.WriteLine("鹦鹉:有翅膀还能吃");
}
public void SayHi()
{
Console.WriteLine("鹦鹉学舌,会\"说话\"");
}
public void Fly()
{
Console.WriteLine("鹦鹉在飞");
}
}
//实例化对象
static void Main(string[] args)
{
IFlyable mq = new MQ();
mq.Fly();
Console.WriteLine("");
IFlyable yw = new YW();
yw.Fly();
Console.WriteLine("");
ISayable say = new YW();
say.SayHi();
Console.ReadKey();
}
- 上一篇: c#简单工厂、抽象工厂、反射
- 下一篇: C#设计模式(3)——工厂方法模式
猜你喜欢
- 2025-01-16 C#13和 .NET9高级功能解析:.NET高手必备技能
- 2025-01-16 C#使用Autofac实现控制反转IoC和面向切面编程AOP
- 2025-01-16 C#设计模式(3)——工厂方法模式
- 2025-01-16 c#简单工厂、抽象工厂、反射
- 2025-01-16 C# 13 和 .NET 9 全知道 :9 处理文件、流和序列化 (1)
- 2025-01-16 Effective C++ 条款07 为多态基类声明virtual析构函数
- 2025-01-16 C# 数据结构和算法 :03 数组和排序(五)
- 2025-01-16 从零开始自学C#基础的最后一天——集合
- 2025-01-16 多态 C#
- 2025-01-16 C#入门篇章—Class类专题
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)