前言
前几天,我们又进行了一遍设计模式的学习,重温了一遍,感觉就是不一样。不仅仅是理解的更加深刻了一点,更重要的是,我发现了很多以前没有注意过的东西。
而这次活动呢,总体来说还是收获满满的。很大程度方便了我们再进行合作机房时候对设计模式的理解以及运用。所以说,学了之后就要用,要不用,学他干嘛?多运用一些是自己变得更加方便的工具、思想,我们进步的才能更快。接下来,就是我总结收获的时刻了。【设计模式】之 透过工厂方法看 抽象类和接口
定义
什么是抽象?什么是接口?答: 抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征; 接口是 两个物体的口子相连接的地方。
理解
如何理解抽象类?如何理解接口?抽象类: 在 面向对象 的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类,运用到我们的定义,就是把一些具有相同特征的东西进行汇总,找出他们的共同特性去进行封装,抽象出来一个类,然后让具体的子类去继承它,最后再拓展出自己特有的方法,去实现自己想要实现的东西
而接口呢?接口里面全都是定义了一些没有具体实现的方法。然后让一个具体的类去实现这个方法。
综合呢: 接口实现和类继承的规则不同,为了数据的安全,继承时一个类只有一个直接父类,也就是单继承,但是一个类可以实现多个接口,接口弥补了类的不能多继承缺点,继承和接口的双重设计既保持了类的数据安全也变相实现了多继承。
实战
那现在我们就进行一个小例子:class A { public virtual void print() { Console.WriteLine("A::print()"); } } class B : A { public override void print() { Console.WriteLine("B::print()"); } public void abcde() { Console.WriteLine("liweizhong"); } } class C : B { public void print(A a) { a.print(); } public override void print() { Console.WriteLine("C::print()"); } static void Main(string[] args) { A a = new A(); A pa = new A(); A pb = new B(); A pc = new C(); B b = new B(); C c = new C(); B f = new B(); a.print(); b.print(); c.print(); pa.print(); pb.print(); pc.print(); f.print(); f.abcde(); pc.print(); c.print(a); c.print(b); c.print(c); String str1 = pa.GetType().ToString(); String str2 = pb.GetType().ToString(); String str3 = pc.GetType().ToString(); Console.WriteLine(str1); Console.WriteLine(str2); Console.WriteLine(str3); Console.ReadKey(); }
结果是啥呢?
在这里面呢,Class A是父类,而B和C是子类,具体的情况就是,B继承A,C继承B,可是在B继承A的这个问题上,B类里面又有了一个自己拓展的方法。那会出现什么情况呢?
当我们用对象pb的时候,是这样的:![]()
可是当我们用b的时候,是这样的:![]()
收获:意思就是如果采用 A pb=new B(),时,pb只能用B从A里面继承的方法,而不能用自己拓展的方法, 而用B b=new B() 的时候,就可以用自己的所有方法。
那这是为什么呢?说到这里,就要说一句话“父类的引用指向子类的对象”,如何理解呢?
A pb=new B();
他表示,我定义了一个A类型的引用,指向新建的B类型的对象。因为B是继承父类A的,所以,A类型的引用可以指向B类型的对象,这是“向上转型”。但是,因为子类是对父类的一个改进和扩充,所以一般子类在功能上较父类更强大,属性较父类更独特, 定义一个父类类型的引用指向一个子类的对象既可以使用子类强大的功能,又可以抽取父类的共性。 所以,父类类型的引用可以调用父类中定义的所有属性和方法,而对于子类中拓展定义父类中没有的方法,父类引用是无法调用的;
那接下来就是接口了。接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体。他所有的方法都是要有子类去进行实现,而且绝对不允许子类里面有任何除了接口定义的方法外的任何拓展,想想我们的工厂,是不是很容易理解了呢?
所以接下来就得说我们的工厂方法的那句代码了:IFactory factory =new AddFactory();
这里用接口大家都应该理解了,那天师哥师姐讲的也很清晰。但是如果我们把接口IFactory 换成 抽象类Factory可以吗?从上面了解到,肯定也是可以的,如果是AddFactory就更没有问题了。
那现在我们假设啊,如果在AddFactory里面还有他自己定义的方法是,这样写还行吗?答案是,那就错了,因为他的这种写法不允许子类定义父类没有的方法。和接口的作用一样了。
1、接口是对动作行为的抽象,抽象类是对根源特性的抽象;2、抽象类用来被继承,接口用来被实现3、接口可以多继承,抽象类只能单继承(子类只能继承一个父类)4、接口是抽象类的变体,接口中所有的方法都是抽象的。而抽象类是声明方法的存在而不去实现它的类。5、接口定义方法,不能实现,而抽象类可以实现部分的方法6、接口中基本的数据类型为static,而抽象类不是7、接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的8、实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法,一般的应用里,最顶级的是接口,然后是抽象类实现接口,最后才到 具体类实现没有9了
所以,当你注意的是一个事物的本质的时候,用抽象;而当你关注一个动作,一个行为的时候,用接口更加方便
小结:
通过一次这样的活动,我就发现了这么多以前没有注意到的东西,所以,这样的活动应该多多举办,大家之间多多交流。学习就是一个反复的过程,不停地反刍,理解的才会更深,发现的才会更多。(请继续关注下文)