设为首页收藏本站【C#】第九章 OOP之类继承及多态
繁体中文

单小喏中文网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

单小喏中文网欢迎你的光临!!!
查看: 2114028|回复: 0

【C#】第九章 OOP之类继承及多态

[复制链接]

85

主题

89

帖子

1246

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
1246

来自- 安徽合肥

扫一扫,手机访问本帖
发表于 2014-4-21 22:41:48 | 显示全部楼层 |阅读模式
类继承:一个类具有某一个类的特征(成员),而且还具体这个类所不具有的特征。这个过程我们称为类的继承。(Extends),原来的类(被继承的类)我们称为基类/父类,继承的类,我们称为派生类/子类
看源码,定义父类:
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace test
{
    class People
    {
        private string name="张三";//姓名字段
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        /// <summary>
        /// 父类方法
        /// </summary>
        public void Say()
        {
            Console.WriteLine("我是人");
        }
    }
}


定义子类:
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace test
{
    class Teacher : People
    {
        public void Say(string cont)
        {
            Console.WriteLine("我是子类teacher中方法" + cont);
        }
    }
}


再定义子类:
[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace test
{
    class Student : People
    {
        public void Say(string cont)
        {
            Console.WriteLine("我是子类student中方法" + cont);
        }
    }
}


在Main方法中测试:
[AppleScript] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace test
{
    class Program
    {
        static void Main(string[] args)
        {
            Student s1 = new Student();
            s1.Say();
            s1.Say("子学");
            Console.WriteLine(s1.Name);
            Teacher t1 = new Teacher();
            t1.Say();
            t1.Say("子老");
            t1.Name = "李四";
            Console.WriteLine(t1.Name);
        }

    }
}


类修饰符:也叫访问修饰符,可以用在类成员、类本身。在C#中访问修饰有以下这些,将分别举例讲解
public、internal、protected、private、static、virtual、sealed、abstract
公共修饰符用在类成员的属性、方法中,类的对象才可以访问(可以.出来),否则就访问不了。
[C#] 纯文本查看 复制代码
namespace test
{
    class People
    {
        private string name="张三";//姓名字段
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        /// <summary>
        /// 父类方法
        /// </summary>
        public void Say()
        {
            Console.WriteLine("我是人");
        }
    }
}
 People p1 = new People();
            p1.Say();//可以访问
            //p1.name;//类的成员不是public类的对象都无法访问


内部默认(省略)的修饰符。用在类的成员中(用在类成员中最好不要省),外部(其他的类库)是无法访问的,只能在类的本身、子类中进行访问。
父类:
[C#] 纯文本查看 复制代码
namespace test
{
    class People
    {
        internal string name = "张三";//姓名字段

        /// <summary>
        /// 父类方法
        /// </summary>
        internal void Say()
        {
             Console.WriteLine("我是人"+this.name);//类本身中访问
        }
    }
}


子类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Student : People
    {
        public Student()
        {
            Console.WriteLine(this.name);
        }
    }
}


在Main方法中调用
[C#] 纯文本查看 复制代码
            People p1 = new People();
            Console.WriteLine(p1.name);//内部修饰符
            p1.Say();//内部修饰符


保护修饰符:成员只能在类本身和子类中进行访问。
父类:
[C#] 纯文本查看 复制代码
namespace test
{
    class People
    {
        protected string name = "张三";//姓名字段
        /// <summary>
        /// 父类方法
        /// </summary>
        protected void Say()
        {
            Console.WriteLine("我是人"+this.name);//类本身中访问
        }
    }
}


子类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Student : People
    {
        public Student()
        {
            Console.WriteLine(this.name);//可以访问
        }
    }
}


在Main方法中测试:
[C#] 纯文本查看 复制代码
People p1 = new People();
            p1.name; p1.Say();//是无法访问的


私有修饰符:成员只能在类本身中访问,子类或其他都无法访问。
父类:
[C#] 纯文本查看 复制代码
namespace test
{
    class People
    {
        private string name = "张三";//姓名字段
        /// <summary>
        /// 父类方法
        /// </summary>
        private void Say()
        {
            Console.WriteLine("我是人"+this.name);//类本身中访问
        }
    }


子类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Student : People
    {
        public Student()
        {
           // Console.WriteLine(this.name);//无法访问
        }
    }
}


在Main方法中测试:
[C#] 纯文本查看 复制代码
People p1 = new People();
            //p1.name; p1.Say();//是无法访问的


特殊情况,其他的类库中的成员,我们想进行访问可以使用internal或public
类People1
[C#] 纯文本查看 复制代码
namespace test1//同一个类库(命名空间)
{
    public class People1 //类要加public
    {
        internal string name = "张三";//姓名字段

        /// <summary>
        /// 父类方法
        /// </summary>
        internal void Say()
        {
            Console.WriteLine("我是人"+this.name);
        }
    }
}


类Class1
[C#] 纯文本查看 复制代码
namespace test1 //同一个类库(命名空间)
{
    class Class1
    {
        public Class1() {
            People1 p1 = new People1();
            p1.name;//这里可以访问
            p1.Say();
        }
    }
}


主要类库中Main方法是无法访问的。
[C#] 纯文本查看 复制代码
People1 p1 = new People1();
p1.name; p1.Say();//无法访问

总结:public、internal、proctected、private访问权限越来越低。分别用在类和类成员访问的权限如下表 c#第九章OOP之类继承.jpg

protected类成员访问的例子:
父类:
[C#] 纯文本查看 复制代码
namespace test1//同一个类库(命名空间)
{
    class People1 //类要加public
    {
        protected string name = "张三";//姓名字段

        /// <summary>
        /// 父类方法
        /// </summary>
        protected void Say()
        {
            Console.WriteLine("我是人" + this.name);
        }
    }
}


子类:
[C#] 纯文本查看 复制代码
namespace test1 //同一个类库(命名空间)
{
    class Class1 : People1
    {
        public Class1()
        {
            //People1 p1 = new People1();这里不能用实例化去访问。
            Console.WriteLine(this.name);//这里可以访问
            this.Say();
        }
    }
}

PS:private的类成员可以被继承,但是无法访问。

方法覆盖:在子类中定义一个与父类同名、参数个数、类型一致(返回值可以不一致)的方法。权限要大于等于父类权限。
父类:
[C#] 纯文本查看 复制代码
  class Class1
    {
        internal void Say()
        {
            Console.WriteLine("我是父类方法");
        }
    }

子类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Class11 : Class1
    {
    }
}

在Main方法中调用
[C#] 纯文本查看 复制代码
Class1 c1 = new Class1();
            c1.Say();
            Class11 c11 = new Class11();
            c11.Say();//发现输出的内容和父类是一样的,继承。但是现在我想输出的内容改变一下
            Class1 c2 = new Class11();//父类new子类
            c2.Say();//调用的方法是父类还是子类呢?

这里会有2个问题:
1、父类和子类调用的方法输出的内容都是一样的,不容易区分到底调用的是父类还是子类
。发现输出的内容和父类是一样的,继承。但是现在我想输出的内容改变一下以示区别
2、父类可以向子类实例化(里氏替换原则,多态),并且调用方法。这个调用的是父类还
是子类方法呢? 方法覆盖的解决方法:
父类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Class1
    {
        internal void Say()
        {
            Console.WriteLine("我是父类方法");
        }
    }
}

子类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Class11 : Class1
    {
        //在子类中定义一个与父类同名、参数个数、类型一致(返回值可以不一致)。权限要大于等于父类权限。
        //方法覆盖,一般加上new这样不会出现警告并且顺序和修饰符可以随意。
        internal new void Say()
        {
            base.Say();//在子类方法覆盖中,还可以调用父类的方法
            Console.WriteLine("我是子类方法");
        }
    }
}

在Main方法中测试:
[C#] 纯文本查看 复制代码
  Class1 c1 = new Class1();
            c1.Say();
            Console.WriteLine("********我是分割线*********");
            Class11 c11 = new Class11();
            c11.Say();//发现输出的内容和父类是一样的,继承。但是现在我想输出的内容改变一下
            Console.WriteLine("********传说中的分割线*********");
            Class1 c2 = new Class11();//父类new子类
            c2.Say();//调用的方法是父类还是子类呢?发现调用的是父类方法,子类方法会被覆盖。

构造方法与方法覆盖:
父类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Class1
    {
        internal void Say()
        {
            Console.WriteLine("我是父类方法");
        }
        public Class1() {
            Console.WriteLine("我是父类构造方法");
        }
    }
}

子类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Class11 : Class1
    {        public Class11()
        {
            //在子类中,只要实例化父类的构造方法会在子类所有方法之前调用一次。
            Console.WriteLine("我是子类构造方法");
        }
        new internal void Say()
        {
            Console.Write("在子类方法中调用父类方法:");
            base.Say();
            Console.Write("在子类方法中调用父类方法之后,加上自己的功能:");
            Console.WriteLine("我是子类输出方法");        }
        //子类有父类没有的方法
        public void Test()
        {
            Console.WriteLine("子类中父类没有的方法");
        }
    }
}

在Main方法中测试:
[C#] 纯文本查看 复制代码
Class1 c1 = new Class1();
            c1.Say();
            Console.WriteLine("*********华丽的分割线*********");
            Class11 c11 = new Class11();
            c11.Say();
            Console.WriteLine("*********传说中的华丽分割线*********");
            Class1 c2 = new Class11();//实例化的是子类对象
            c2.Say();//方法覆盖
            //c2.Test();//因为有覆盖,所以无法调用

总结:在子类中,只要实例化,父类的构造方法会在子类所有方法之前调用一次。如图
c#第九章OOP之类继承.jpg
方法重写:在方法覆盖中,子类所有的方法会被父类覆盖,以父类向子类实例化,是无法访问的。我们可以改进这一缺陷。子类中方法名相同、参数个数、类型、返回值类型要一致
父类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Class1
    {
        virtual public void Say()
        {
            Console.WriteLine("我是父类方法");
        }
    }
}

子类:
[C#] 纯文本查看 复制代码
namespace test
{
    class Class11 : Class1
    {
        //子类中方法名想用、参数个数、类型、返回值类型要一致
        override public void Say()
        {
            Console.WriteLine("我是子类方法");
        }
        
    }
}

测试:
[C#] 纯文本查看 复制代码
[	DISCUZ_CODE_0	]

总结:在上述方法重写中,发现父类的方法没有作用了,父类的方法我们可以省略实现,并且功能都可以简单的描述,由此可以使用抽象(abstract)方法,抽象方法必须要保存在抽象类中,但是抽象类可以有不是抽象的方法;子类必须要实现抽象方法(不想实现那这个类可以是抽象的);抽象类无法实例化。
父类:
[C#] 纯文本查看 复制代码
[	DISCUZ_CODE_1	]

子类:
[C#] 纯文本查看 复制代码
[	DISCUZ_CODE_2	]

子类:
[C#] 纯文本查看 复制代码
[	DISCUZ_CODE_3	]

测试:
[C#] 纯文本查看 复制代码
[	DISCUZ_CODE_4	]
[color=#333333][font=Arial]//想一想,怎么在Class11中调用Test1方法?可以选择方法覆盖、方法重写、抽象方法[/font][/color] 

sealed密封类,不能被其他类继承。
static静态类与静态成员:

类类型不是基本数据类型,而是引用数据类型。类对象访问不会相互干扰。如果想访问类成
员和对象开辟的空间、地址是唯一和固定可以使用static(静态)
[C#] 纯文本查看 复制代码
[	DISCUZ_CODE_5	]
[	DISCUZ_CODE_6	]


调用
[C#] 纯文本查看 复制代码
[	DISCUZ_CODE_7	]


PS:静态类里只能有静态成员。访问只能直接 类名.成员。静态类和密封类一样不能被继承。
本文章来源于:学玩网









上一篇:简谱的初步认识(2)
下一篇:【C#】第十章 多态与接口

帖子地址: 



+1
2114028°C
沙发哦 ^ ^ 马上
*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

 
发评论,即可赢取积分欧!

申请友链|意见反馈|小黑屋|手机版|Archiver|单小喏中文网 ( 皖ICP备13012632号-1 |网站地图  

GMT+8, 2016-12-8 17:53 , Processed in 0.279459 second(s), 51 queries .

Powered by danxiaonuo

© 2013-2016 danxiaonuo.

快速回复 返回顶部 返回列表