扣响C#之门笔记-第九章

9.1 继承的概念

继承:

基类(父类):不解释

派生类(子类):不解释

派生类中自动拥有了父类的定义的变量和函数,每个派生类也可以成为其他新派生类的父类;

9.2 由父类派生子类

1.继承的语法:

 

eg

 class Animal               //(1)定义父类
    {
        public double weight;
        private double temperature;
        public Animal()
        {
            weight = 0;
            temperature = 0;
        }
        public void eat()
        {
            Console.WriteLine("eat");
        }
        public void breathe()
        {
            Console.WriteLine("breathe");
        }
        public void sleep()
        {
            Console.WriteLine("sleep");
        }
    }

    class Mammal:Animal       //(2)定义子类:继承于父类
    {
        private string skins;
        public Mammal()
        {
            skins = "皮";
        }

        public string Skins
        {
            set { skins = value; }
            get { return skins; }
       }
        public void run()
        {
            Console.WriteLine("run");
        }
        public void scukle()
        {
            Console.WriteLine("scukle");
        }
    
    }

    class Program
    {
        static void Main(string[] args)
        {
            Mammal best = new Mammal();
            Console.WriteLine(best.weight); // (3)使用继承于父类中的属性
            Console.WriteLine(best.Skins); //       使用新添加的属性

            best.eat(); //使用继承于父类中方法
            best.run();//使用子类添加的方法
            Console.ReadKey();

        }
    }

9.3 protected 成员

父类中private修饰的成员(类成默认修饰符是private),只能在类自己内部使用,不能再子类中使用;解决这个问题有两种方法:

(1)使用protected 修饰,protected 成员不能被类外部使用,但是在子类能使用(如果将成员修饰符换成public,但是这样会让类失去封装性);

(2)定义一个public的属性实现;

private成员:只有本类内能使用(本类的对象都不能使用)

    class Animal               
    {
        private double weight;
    }
    class dog:Animal             
    {    
        void print()
        {
            weight=30; //error,无法访问
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Animal a = new Animal();
            a.weight = 30;  //error,无法访问
        }
        }
    }

protected 成员:只有本类(废话)和子类中能使用

    class Animal               
    {
        protected double weight;
    }
    class dog:Animal             
    {    
        void print()
        {
            weight=30; //protected 成员,子类可以访问
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Animal a = new Animal();
            a.weight = 30;  //error,protected 成员,外部无法访问
        }
        }
    }

9.4 虚函数与重写

(1)虚函数就是用virtual修饰的函数,一般在基类上设计虚函数,在派生类中重写(Overwrite);

    class Animal
    {
        private double temperature;   //(1)虚函数
        public virtual void eat()
        {
            Console.WriteLine("eat");
        }
    }
    class dog : Animal
    {
        private double temperature;
        public override void eat()   //重写虚函数
        {
            Console.WriteLine("dog eat");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            dog g = new dog();
            g.eat();
            Console.ReadKey();

        }
    }

(2)重新(override)与重载:

重载:是指在同一个类中,有多个函数名相同,但是参数类型/个数不同的多个函数;重载发生在同一个类中;(系统根据调用的 实参数个数和类型自动匹配对应重载的函数)

重写:是指子类中定义了和父类同名的函数,并改写这个方法;重写发生在继承关系中;(系统根据对象的实际类型调用对应函数,如果对象是父类对象,就调用父类中方法,如果是是子类对象,则调用子类对象)

9.5 函数的隐藏

派生类可以使用new 关键修饰函数,从而隐藏基类中的同名函数;

new 关键字:用在函数前表示隐藏(覆盖)父类中的同名函数(可以不加new也可以覆盖,但是编译有告警)

    class Animal
    {
     
        public  void eat()
        {
            Console.WriteLine("eat");
        }
    }
    class dog : Animal
    {

        public new void eat()  //new 关键字,可以不加new也可以覆盖,但是编译有告警
        {
            Console.WriteLine("dog eat");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            dog g = new dog();
            g.eat();
            Animal a = new Animal();
            a.eat();
            Console.ReadKey();
        }
    }

6.6 Base关键字

利用关键字base,可以在子类中(只能在子类中)调用父类的重写的后者隐藏方法;

 

    class Animal
    {
     
        public  void eat()
        {
            Console.WriteLine("eat");
        }
    }
    class dog : Animal
    {

        public new void eat()  
        {
            base.eat();  //base关键字
        }
    }

6.7抽象类和抽象函数

(1)抽象类:就是用就是用abstrct修饰的类

(a)抽象类不能实例化;

(b)抽象类和抽象函数,抽象属性没有什么必然关系,抽象类内部可以是抽象方法,也可以是一般法方法,或者都有都可以(但是有抽象方法的类一定是抽象类);

(c)如果一个非抽象类继承抽闲类,那么这个类,必须要重写(override)抽象父类中所有抽象方法,否则,这个类就必须还是抽象函数;

    public  abstract class Animal
    {
          private void eat()
          {
              Console.WriteLine("");
          }
          public abstract void run();  
          public abstract void sleep();
    }

    public class dog : Animal    //错误,子类没有重写完父类所有抽象方法,这个类必须还是抽象函数
      {
        public  override void run(){}
        //
      
      }

(2)抽象函数:就是用就是用abstrct修饰的函数;(所有抽象成员的访问等级必须是public)

(a)抽象函数是一种特殊的虚函数,必须在抽闲类中定义;有抽象方法的类一定是抽象类;

(b)抽象函数定义时候只能有函数签名,不能有任何执方法体(包含{}都不能有);

 public  abstract class Animal
    {
          private void eat()
          {
              Console.WriteLine("");
          }
          public abstract void run(){};  //错误,抽象方法不能有任何方法体
          public abstract void sleep();
    }

(C)抽象方法,抽象属性必须为public,否则编译出错;

      abstract class Animal
    {
          private void eat()
          {
              Console.WriteLine("eat");
          }
           abstract void run();   //错误抽象成员不能为私有的,只能为public
          public abstract void sleep();
    }

(3)抽象属性:

(a)也可以定义抽象属性:抽象属性也不能有任何实现代码({}都不能有)

   abstract class Animal 
        {
            abstract public int Age
            {
                set; //不能有属性也不能有具体实现,({}都不能有)
                get;
            }

        }

(b)同样的,抽闲属性,也必须在继承类全部中用overridi,重写,否则这个类也必须为抽象类;

        abstract class Animal 
        {
            string name;
            abstract public int Age  //抽象属性
            {
                set; 
                get;
            }
        }
        class dog : Animal
        {
            public override int Age  //重写属性
            {
                set { }
                get { return 3; }
            }       
        }

(4)小结:

abstarct 可以修饰 方法,属性,不能修饰字段

1.抽象方法

(1)抽象方法就是用abstract 修饰的方法;

(2)抽象方法都必须是只有函数签名,不能有函数实现(包含{}都不能有);

public abstract void eat(){}
 //错误 1 “Test09.Animal.eat()”无法声明主体,因为它标记为 abstract

(3)抽象方法都public的,必须显示申明为public的(默认不加任何修饰符是private);

   abstract void eat();  
 //错误 1 “Test09.Animal.eat()”: 虚拟成员或抽象成员不能是私有的

(4)抽象方法只能定义在抽象类中;(也就是说有一个抽象方法/属性的类必须是抽象类)

(5)抽象方法也不能是静态的;

public static  abstract void eat();

 //错误 1 静态成员“Test09.Animal.eat()”不能标记为 override、virtual 或 abstract

2.抽象属性:和抽象类好像,参考抽象方法即可;

(6)抽象属性方法就是用abstract 修饰的属性;

(7)抽象属性必须没有任何实现代码;

(8)抽象属性都public的,必须显示申明为public的(默认不加任何修饰符是private);

(9)抽抽象属性只能定义在抽象类中;(也就是说有一个抽象方法/属性的类必须是抽象类)

(5)抽象属性也不能是静态的,私有的;

 

3.抽象类:

(1)抽象类就是用abstract修饰的类,抽象类中可以有非抽象的成员(实体方法,字段等),抽象成员必须定义在抽象类内部;

       abstract class Animal
    {
        string name; 
        public abstract int Age  
        {
            set;
            get;
        }
        public abstract void eat(); 
    }

(2)抽象类不能为静态的或者密封的;

static abstract class Animal { }

//error  错误 1 “Test10.Animal”: 抽象类不能是密封的或静态的

(3)抽象类不能实例化,如果一个类要继承抽象类,就需要实现重写(override)抽象类中所有(注意是所有)抽象成员,否则这个类还得是抽象类(因为有一个抽象成员的类就必须是抽象类;

       abstract class Animal
    {
        string name; 
        public abstract int Age  
        {
            set;
            get;
        }
        public abstract void eat(); 
    }

    class dog : Animal   //error 没有重写(override)完抽象类中所有的抽象成员
    {
        public override int Age  
        {
            set { }
            get { return 3; }
        }

    }

9.8 密封类和密封函数

(1)密封类(用Sealed修饰的的类)是一种不能被继承的类

 public  sealed class Aniaml
    {
        int Age 
        {
        get { return 0; }
        set { }
        }
      public   int eat()
       {
            return 0; 
       }
    }

    class dog : Aniaml   //无法 继承sealed的类
    {
    }

 

(2)密封方法(用Sealed修饰的的方法)是一种不能被重写的方法;

注意:sealed修饰方法/属性时,只能在override重写时候使用,意思是说禁止下次重写,父类总无法使用;

修饰类时候无此限制;

class dog : Aniaml 
    {
        sealed override int Age { set { } get { return 0; } }
        //sealed 修饰方法时候,必须有override关键字
    }

9.9 派生类的构造函数

1.构造函数过程

创建对象时,系统先先调用父类的构造函数,(初始化基类成员),然后再调用子类的构造函数(初始化子类成员);

是一个由基类向派生类逐步构建的过程;

删除对象是,先调用子类的析构函数(销毁子类成员),然后调用父类的析造函数(销毁父类中的成员);

是一个由派生类向父类逐步销毁的过程;

    public class Aniaml
    {
        public int age;
        public int weighet;
        public Aniaml()
        {   age = 0;
            weighet=0;
            Console.WriteLine("Aniaml的构造函数");
        }
         ~Aniaml()
        {
            
            Console.WriteLine("销毁Aniaml");
        }
    }

    class Dog : Aniaml
    {
        public Dog()
        {
            age = 1;
            weighet=1;
            Console.WriteLine("Dog的构造函数");
        }
         ~Dog()
        {   age = 1;
            weighet = 1;
            Console.WriteLine("销毁DOg");
        }
    }


    class snoopy : Dog
    {
        public snoopy()
        { string name = "snoopy";
        age = 3;
        weighet = 3;
        Console.WriteLine("snoopy的构造函数");
        }
        ~snoopy()
        {
            Console.WriteLine("销毁snoopy"); 
        }   
    }
    class Program
    {
        static void Main(string[] args)
        {
            new snoopy();    //创建对象时候,从父类开始,依次向子类调用构造函数;
            Console.ReadKey();
                            //销毁对象时候,从子类析构函数开始,依次向父类调用函数析构;
        }
    }

2.带参数的构造函数

给给构造函数设置参数,在实例化对象时候,可以通过形参设置成员变量初始值,比较简单;

注意:

(1)如果人为类添加任何一个构造函数,系统就不会提供默认(无参数)的构造函数了,此时实例实话就不能用无参数的构造函数了;

(当然,如果人认为提供一个无参数的构造函数,当然才能能用)

    class A
    { 
      public int a;
      public A(int a)
      {
          Console.WriteLine(a);
      }
    }
    class Program
    {
        static void Main(string[] args)
        {
            A aa = new A();//error 系统已经无默认构造函数,无法调用
            Console.WriteLine(aa.a);
            Console.ReadKey();
        }
        
    }

(2)由于子类不能访问父类中的private成员,因此不能通过子类构造函数初始化父类的私有变量(可用用公共属性实现),但是可以显式调用父类的构造函数实现

一般不用,应该尽量保持不变,使用系统默认方式,让父类构造函数自己初始自己的私有属性;

 

9.2 万类之源 Object

(1)C#中的所有类都直接或者间接继承于Object类,如果定义一个类时候没有指定其父类,则编译器自动使他继承于Object;

【所有类都可以转为Object类型】

Object类成员含数:

(2)Tostring()是Object类中的虚函数,所有的类都继承了该函数,功能是返回与类相关的字符串

很多类都重写ToString函数,因此就能将很多类型自动转换为字符串;

int i = 3;
string s=i.ToString();

实际上我们直接这样,系统或自动调用I的对应类型toString()方法,转为字符串;

 Console.WriteLine("shu"+i);

(3)重写Tostring 方法:

 class A
    {
        public override string ToString()  //从写了父类object的ToString方法
        {
            return "A的ToString方法";
        }   
    }
    class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            Console.WriteLine(a);
            Console.ReadKey();
        }
    }

 

posted on 2016-08-03 00:26  JUstForU  阅读(363)  评论(0)    收藏  举报

导航