c#面向对象中的继承初步认识
最近在看一些设计模式方面的东西,渐渐感觉到自己的基础很差,所以再回过头来学习一下基础的东西。
简单的才是最容易接受的。
简单的才是最容易接受的。
1/// <summary>
2 /// 抽象鸭子类
3 /// msdn:abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。
4 /// 在类声明中使用 abstract 修饰符以指示某个类只能是其他类的基类。
5 /// 标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。
6 /// 抽象类具有以下特性:
7 /// 抽象类不能实例化。
8 /// 抽象类可以包含抽象方法和抽象访问器。
9 /// 不能用 sealed(C# 参考)修饰符修改抽象类,这意味着抽象类不能被继承。
10 /// 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现.
11 /// 在方法或属性声明中使用 abstract 修饰符以指示方法或属性不包含实现。
12 /// 抽象方法具有以下特性:
13 /// 抽象方法是隐式的虚方法。
14 /// 只允许在抽象类中使用抽象方法声明。
15 /// 因为抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。
16 /// 实现由一个重写方法提供,此重写方法是非抽象类的成员。
17 /// 在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
18 /// 除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
19 /// 在静态属性上使用 abstract 修饰符是错误的。
20 /// 在派生类中,通过包括使用 override 修饰符的属性声明,可以重写抽象的继承属性。
21 /// 抽象类必须为所有接口成员提供实现。
22 /// 实现接口的抽象类可以将接口方法映射到抽象方法上。
23 /// </summary>
24 public abstract class AbstractDuck //这个修饰符很重要
25 {
26 //字段
27 protected int _x=0;
28 protected int _y=0;
29 public abstract int X { get;}//只读
30 public abstract int Y { get;set; }//读写
31
32 //void Speak(string name); error:必须声明abstract or extern
33 public abstract void Speak(string name);
34 //abstract void Eat();error:“OOPDemo.AbstractDuck.Eat()”: 虚拟成员或抽象成员不能是私有的
35 public abstract void Eat();
36 //public abstract void Drink() error:声明为abstract 的方法不能包含实现
37 //{
38 // Console.WriteLine("i am a duck,i can drink");
39 //}
40 public void Drink()//实现的方法
41 {
42 Console.WriteLine("i am a duck,i can drink");
43 }
44 }
45 ///备注:抽象类可以继承接口,但必须包含接口成员的显示声明,abstract void MethodName()
2 /// 抽象鸭子类
3 /// msdn:abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。
4 /// 在类声明中使用 abstract 修饰符以指示某个类只能是其他类的基类。
5 /// 标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。
6 /// 抽象类具有以下特性:
7 /// 抽象类不能实例化。
8 /// 抽象类可以包含抽象方法和抽象访问器。
9 /// 不能用 sealed(C# 参考)修饰符修改抽象类,这意味着抽象类不能被继承。
10 /// 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现.
11 /// 在方法或属性声明中使用 abstract 修饰符以指示方法或属性不包含实现。
12 /// 抽象方法具有以下特性:
13 /// 抽象方法是隐式的虚方法。
14 /// 只允许在抽象类中使用抽象方法声明。
15 /// 因为抽象方法声明不提供实际的实现,所以没有方法体;方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。
16 /// 实现由一个重写方法提供,此重写方法是非抽象类的成员。
17 /// 在抽象方法声明中使用 static 或 virtual 修饰符是错误的。
18 /// 除了在声明和调用语法上不同外,抽象属性的行为与抽象方法一样。
19 /// 在静态属性上使用 abstract 修饰符是错误的。
20 /// 在派生类中,通过包括使用 override 修饰符的属性声明,可以重写抽象的继承属性。
21 /// 抽象类必须为所有接口成员提供实现。
22 /// 实现接口的抽象类可以将接口方法映射到抽象方法上。
23 /// </summary>
24 public abstract class AbstractDuck //这个修饰符很重要
25 {
26 //字段
27 protected int _x=0;
28 protected int _y=0;
29 public abstract int X { get;}//只读
30 public abstract int Y { get;set; }//读写
31
32 //void Speak(string name); error:必须声明abstract or extern
33 public abstract void Speak(string name);
34 //abstract void Eat();error:“OOPDemo.AbstractDuck.Eat()”: 虚拟成员或抽象成员不能是私有的
35 public abstract void Eat();
36 //public abstract void Drink() error:声明为abstract 的方法不能包含实现
37 //{
38 // Console.WriteLine("i am a duck,i can drink");
39 //}
40 public void Drink()//实现的方法
41 {
42 Console.WriteLine("i am a duck,i can drink");
43 }
44 }
45 ///备注:抽象类可以继承接口,但必须包含接口成员的显示声明,abstract void MethodName()
1/// <summary>
2 /// 接口鸭子类
3 /// msdn:接口具有下列属性:
4 /// 接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
5 /// 不能直接实例化接口。(但可以用接口实例化一个对象)
6 /// 接口可以包含事件、索引器、方法和属性。
7 /// 接口不包含方法的实现。
8 /// 类和结构可从多个接口继承。
9 /// 接口自身可从多个接口继承。
10 /// 接口描述可属于任何类或结构的一组相关行为。
11 /// 接口可由方法、属性、事件、索引器或这四种成员类型的任何组合构成。
12 /// 接口不能包含字段!
13 /// 接口成员一定是公共的!
14 /// </summary>
15 public interface InterfaceDuck //鸭子都很懒,就让他只会吃饭睡觉吧,要是鸭子能挣钱,估计所有人都养鸭子去了:)
16 {
17 //public void Eat(string food);访问修饰符是无效的。
18 void Eat(string food);
19 void Sleep();
20 int X
21 { get; }
22 int Y
23 {
24 get;
25 set;
26 }
27 }
2 /// 接口鸭子类
3 /// msdn:接口具有下列属性:
4 /// 接口类似于抽象基类:继承接口的任何非抽象类型都必须实现接口的所有成员。
5 /// 不能直接实例化接口。(但可以用接口实例化一个对象)
6 /// 接口可以包含事件、索引器、方法和属性。
7 /// 接口不包含方法的实现。
8 /// 类和结构可从多个接口继承。
9 /// 接口自身可从多个接口继承。
10 /// 接口描述可属于任何类或结构的一组相关行为。
11 /// 接口可由方法、属性、事件、索引器或这四种成员类型的任何组合构成。
12 /// 接口不能包含字段!
13 /// 接口成员一定是公共的!
14 /// </summary>
15 public interface InterfaceDuck //鸭子都很懒,就让他只会吃饭睡觉吧,要是鸭子能挣钱,估计所有人都养鸭子去了:)
16 {
17 //public void Eat(string food);访问修饰符是无效的。
18 void Eat(string food);
19 void Sleep();
20 int X
21 { get; }
22 int Y
23 {
24 get;
25 set;
26 }
27 }
1/// <summary>
2 /// 继承 抽象类
3 /// </summary>
4 public class JackDuckFromAbstract:AbstractDuck
5 {
6 public override int X
7 {
8 get { return _x; }
9 }
10 public override int Y
11 {
12 get { return _y; }
13 set { _y = value; }
14 }
15 //protected override void Eat() 访问修饰符不可改变
16 //{
17 // Console.WriteLine("i am jack duck,i like eating");
18 //}
19 public override void Eat()
20 {
21 Console.WriteLine("i am jack duck,i like eating");
22 }
23 public override void Speak(string name)
24 {
25 Console.WriteLine("hi {0},i am jack,i am {1} years old",name,this.Y);
26 }
27 public new void Drink()//new 隐藏夫类里的Drink()
28 {
29 Console.WriteLine("i am jack's drink method,i drink beer");
30 }
31 }
2 /// 继承 抽象类
3 /// </summary>
4 public class JackDuckFromAbstract:AbstractDuck
5 {
6 public override int X
7 {
8 get { return _x; }
9 }
10 public override int Y
11 {
12 get { return _y; }
13 set { _y = value; }
14 }
15 //protected override void Eat() 访问修饰符不可改变
16 //{
17 // Console.WriteLine("i am jack duck,i like eating");
18 //}
19 public override void Eat()
20 {
21 Console.WriteLine("i am jack duck,i like eating");
22 }
23 public override void Speak(string name)
24 {
25 Console.WriteLine("hi {0},i am jack,i am {1} years old",name,this.Y);
26 }
27 public new void Drink()//new 隐藏夫类里的Drink()
28 {
29 Console.WriteLine("i am jack's drink method,i drink beer");
30 }
31 }
1/// <summary>
2 /// 继承接口
3 /// </summary>
4 public class FrankDuckFromInterface:InterfaceDuck
5 {
6 public void Eat(string food)//这里不需要显示声明override,抽象类必须的。
7 {
8 Console.WriteLine("hi mm,i am frank ,i like eat {0}",food);
9 }
10 public virtual void Sleep()//可以声明virtual,在被继承就可以override了
11 {
12 Console.WriteLine("hi mm,i am frank ,i like sleeping 2");
13 }
14 int _x;
15 int _y;
16 public int X { get { return _x; } set { _x = value; } }//接口里是只读的,所以实现接口可以改写访问器
17 public int Y { get { return _y; } set { _y = value; } }//实现接口的类的最低要求是接口内容全部被实现
18 }
2 /// 继承接口
3 /// </summary>
4 public class FrankDuckFromInterface:InterfaceDuck
5 {
6 public void Eat(string food)//这里不需要显示声明override,抽象类必须的。
7 {
8 Console.WriteLine("hi mm,i am frank ,i like eat {0}",food);
9 }
10 public virtual void Sleep()//可以声明virtual,在被继承就可以override了
11 {
12 Console.WriteLine("hi mm,i am frank ,i like sleeping 2");
13 }
14 int _x;
15 int _y;
16 public int X { get { return _x; } set { _x = value; } }//接口里是只读的,所以实现接口可以改写访问器
17 public int Y { get { return _y; } set { _y = value; } }//实现接口的类的最低要求是接口内容全部被实现
18 }
1class Program
2 {
3 static void Main(string[] args)
4 {
5 JackDuckFromAbstract jack = new JackDuckFromAbstract();
6 jack.Y = 23;
7 jack.Eat();
8 jack.Speak("trace");
9 jack.Drink();
10
11 FrankDuckFromInterface frank = new FrankDuckFromInterface();
12 frank.Eat("bake duck");
13 frank.Sleep();
14
15 Console.ReadLine();
16 }
17 }
2 {
3 static void Main(string[] args)
4 {
5 JackDuckFromAbstract jack = new JackDuckFromAbstract();
6 jack.Y = 23;
7 jack.Eat();
8 jack.Speak("trace");
9 jack.Drink();
10
11 FrankDuckFromInterface frank = new FrankDuckFromInterface();
12 frank.Eat("bake duck");
13 frank.Sleep();
14
15 Console.ReadLine();
16 }
17 }
问题:
1,抽象类可以包含实现的和非实现的方法吗?
2,对于实现的方法可以加abstract吗?加了有什么效果?不加呢?
3,virtual关键字,如果用sealed修饰了类,再用virtual修饰方法报错吗?
继承抽象类的类,在实现抽象类abstract方法和属性时,必须显示标记override,要不报错.
对于抽象类中的属性,如果只有单一读或者写属性,那么继承类也必须只有一个,擅自添加访问器报错
对于继承自abstract的类,使用了overrider关键字重写,不能再用virtual标记。
对于重写abstract的方法,继承类无法更改访问修饰符,负责报错.
在抽象类里边实现一个private的方法,毫无意义,除非为了给其他成员实现提供便利。
父类里的方法被override了,子类就可以继续override此方法。
暂时先写这些吧。