A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© czwanglei 金牌黑马   /  2014-5-11 17:27  /  2122 人查看  /  17 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 czwanglei 于 2014-5-11 17:28 编辑
  1. Person类
  2. class Person
  3.     {
  4.         private string name;  //定义人的名字
  5.         private int age;     //人的年龄
  6.         private char gender; //人的性别
  7.         public string Name       //下面是分别对三个字段的封装
  8.         {
  9.             get { return name; }
  10.             set { name = value; }
  11.         }
  12.         public int Age
  13.         {
  14.             get { return age; }
  15.             set { age = value; }
  16.         }
  17.         public char Gender
  18.         {
  19.             get { return gender; }
  20.             set { gender = value; }
  21.         }
  22.         public Person ()//显示定义一个构造方法,避免继承的时候出现调用无参的方法时报错
  23.         { }
  24.         public Person(string name,int age,char gender)//有参构造方法,为了给参数赋值
  25.         {
  26.             this.name = name;
  27.             this.age = age;
  28.             this.gender = gender;
  29.         }
  30.         /// <summary>
  31.         /// 定义一个人打招呼的方法
  32.         /// </summary>
  33.         public new  void SayHello()
  34.         {
  35.             Console.WriteLine("我是基类打招的方法");
  36.             Console.WriteLine("大家好,我叫{0},今年{1}岁,我是{2}生.", name, age, gender);
  37.         }
复制代码
  1. Teacher类
  2. class Teacher:Person
  3.     {
  4.         private string name;
  5.         private int age;
  6.         private char gender;
  7.         private int yearsofService;
  8.         public string Name      
  9.         {
  10.             get { return name; }
  11.             set { name = value; }
  12.         }
  13.         public int Age
  14.         {
  15.             get { return age; }
  16.             set { age = value; }
  17.         }
  18.         public char Gender
  19.         {
  20.             get { return gender; }
  21.             set { gender = value; }
  22.         }
  23.         public int YearsofService
  24.         {
  25.             get { return yearsofService; }
  26.             set { yearsofService = value; }
  27.         }
  28.         /// <summary>
  29.         /// Teacher的有参构造方法
  30.         /// </summary>
  31.         /// <param name="name">老师姓名</param>
  32.         /// <param name="age">老师年龄</param>
  33.         /// <param name="gender">老师性别</param>
  34.         /// <param name="yearsofService"></param>
  35.         public Teacher (string name,int age,char gender,int yearsofService):base(name,age,gender)
  36.         {
  37.             this.yearsofService = yearsofService;
  38.         }
  39.         /// <summary>
  40.         /// 定义一个老师的说话的方法
  41.         /// </summary>
  42.         public void SayHello()
  43.         {
  44.             Console.WriteLine("我是父类打招呼的方法");
  45.             Console.WriteLine("大家好,我叫{0},今年{1},教书{2}年了.",name,age,yearsofService);
  46.         }
复制代码
  1. 主函数
  2. class Program
  3.     {
  4.         static void Main(string[] args)
  5.         {
  6.             Teacher t = new Teacher("张老师", 29, '男', 3);
  7.             t.SayHello();
  8.             
  9.             Console.ReadKey();
  10.         }
复制代码
请问 t.SayHello(), 怎么没有获取到"张老师", 29, '男', 3的值。

17 个回复

倒序浏览
本帖最后由 鲤鱼 于 2014-5-11 18:23 编辑
  1. namespace test1
  2. {
  3.     class Person
  4.     {
  5.         private string name;
  6.         private int age;
  7.         private char gender;
  8.         public string Name
  9.         {
  10.             get { return name; }
  11.             set { name = value; }
  12.         }
  13.         public int Age
  14.         {
  15.             get { return age; }
  16.             set { age = value; }
  17.         }
  18.         public char Gender
  19.         {
  20.             get { return gender; }
  21.             set { gender = value; }
  22.         }
  23.         public Person()
  24.         { }
  25.         public Person(string name, int age, char gender)
  26.         {
  27.             this.name = name;
  28.             this.age = age;
  29.             this.gender = gender;
  30.         }
  31.         public  void SayHello()
  32.         {
  33.             Console.WriteLine("我是基类打招的方法");
  34.             Console.WriteLine("大家好,我叫{0},今年{1}岁,我是{2}生.", name, age, gender);
  35.         }

  36.     }
  37.     class Teacher : Person
  38.     {
  39.         private int yearsofService;
  40.         public Teacher(string name, int age, char gender, int yearsofService)
  41.             : base(name, age, gender)
  42.         {
  43.             this.yearsofService = yearsofService;
  44.         }
  45.         public int YearsofService
  46.         {
  47.             get { return yearsofService; }
  48.             set { yearsofService = value; }
  49.         }
  50.         public new void  SayHello()
  51.         {
  52.             Console.WriteLine("我是父类打招呼的方法");
  53.             Console.WriteLine("大家好,我叫{0},今年{1},教书{2}年了.", Name, Age, YearsofService);
  54.         }
  55.         class Program
  56.         {
  57.             static void Main(string[] args)
  58.             {
  59.                 Person t = new Person("张老师", 29, '男');
  60.                 t.SayHello();
  61.                 Teacher x =new Teacher("张老师", 29, '男', 3);
  62.                 x.SayHello();
  63.                 Console.ReadKey();
  64.             }

  65.         }
  66.     }
  67. }
复制代码

点评

啦啦啦,我是甩下代码就肘的潜水员,哇咔咔~  发表于 2014-5-11 18:28

评分

参与人数 1技术分 +1 收起 理由
czwanglei + 1

查看全部评分

回复 使用道具 举报
本帖最后由 continue  于 2014-5-11 17:56 编辑

你在父类和子类中方法的new关键字用反了,
至于这种结果是因为当前调用的是子类中的这三个字段的值,构造函数中传递的是值是赋值给了它集成自父类中的三个属性。你在子类Teach中并没有对这三个字段进行赋值,字段的访问是讲究就近原则,继承的这三个属性和你当前类中声明的这三个字段是没有任何关系的,除了名字相同以外。同样 SayHello() 这个方法的调用也是同样,调用的是子类中的方法,不是父类中的方法
如果要实现获取值,几个办法:
1、把子类中的name,age,gender 这三个字段和属性给干掉不要,同时将子类中的方法 SayHello() 也给干掉。
2,源代码不同,在子类中 SayHello() 方法的参数中将name,age,gender 改为base.Name,base.Age,base.Gender;
3、主程序中就是进行一个类型转换,将子类实例t进行一个转换 Person p = (Person)t;[最好是通过as来实现],然后调用p.sayHello()即可
在好好看看老师的视频吧,我也研究了很久

回复 使用道具 举报
  1. /* 我们从这里开始new Teacher("张老师", 29, '男', 3) =》 调用Teacher (string name,int age,char gender,int yearsofService),在执行函数体前它又调用了base(name,age,gender) =》
  2.      * Person的私有数据被初始化 =》返回Teacher (string name,int age,char gender,int yearsofService),执行函数体,为yearsofService赋值 =》 很明显,现在Teacher的私有数据没有被赋值为理想值而是默认值,因此,当Teacher调用SayHello()就得不到期望的结果
  3.      * 顺带一提,在Teacher内定义的属性把Person定义的属性给掩盖了,因此即使修改Teacher的SayHello(),把使用私有数据改为Teacher的属性,结果还是一样。
  4.      * 还有,Teacher不是父类是子类(派生类)
  5.      */
复制代码
  1. public void SayHello()
  2.         {
  3.             Console.WriteLine("我是父类打招呼的方法");
  4.             Console.WriteLine("大家好,我叫{0},今年{1},教书{2}年了.",Name,Age,YearsofService);
  5.         }
复制代码
话说版主的提问必须拿下。。


点评

这句话,说的好。  发表于 2014-5-11 18:25

评分

参与人数 1技术分 +1 收起 理由
czwanglei + 1

查看全部评分

回复 使用道具 举报
  1. class Teacher:Person
  2.     {
  3.         private int yearsofService;
  4.         public int YearsofService
  5.         {
  6.             get { return yearsofService; }
  7.             set { yearsofService = value; }
  8.         }
  9.         /// <summary>
  10.         /// Teacher的有参构造方法
  11.         /// </summary>
  12.         /// <param name="name">老师姓名</param>
  13.         /// <param name="age">老师年龄</param>
  14.         /// <param name="gender">老师性别</param>
  15.         /// <param name="yearsofService"></param>
  16.         public Teacher (string name,int age,char gender,int yearsofService):base(name,age,gender)
  17.         {
  18.             this.yearsofService = yearsofService;
  19.         }
  20.         /// <summary>
  21.         /// 定义一个老师的说话的方法
  22.         /// </summary>
  23.         public void SayHello()
  24.         {
  25.             Console.WriteLine("我是子类打招呼的方法");
  26.             Console.WriteLine("大家好,我叫{0},今年{1},教书{2}年了.",Name,Age,YearsofService);
  27.         }
  28. }
复制代码
现在我们只需要把重复定义的数据和属性割掉就OK了

评分

参与人数 1技术分 +1 收起 理由
czwanglei + 1

查看全部评分

回复 使用道具 举报
亚伦 发表于 2014-5-11 17:58
话说版主的提问必须拿下。。

分析的不错。
回复 使用道具 举报

不错。缺点:回复别人是最好有分析过程,以及运行结果就更完美了。

点评

我是后发哒,看见有分析就不再掺和啦~~发来给你审查下,我再看看代码呗~~就这样吧,哈哈  发表于 2014-5-11 18:32
回复 使用道具 举报
话说解决的方法是把Person类的SayHello()方法的new去掉,然后在Teacher的SayHello()前加new吧
回复 使用道具 举报
永远的小飞侠 发表于 2014-5-11 22:18
话说解决的方法是把Person类的SayHello()方法的new去掉,然后在Teacher的SayHello()前加new吧 ...

不是的,那个只是隐藏基类的方法。
回复 使用道具 举报
czwanglei 发表于 2014-5-12 13:58
不是的,那个只是隐藏基类的方法。
  1. //Person类
  2.     class Person
  3.     {
  4.         private string name;  //定义人的名字
  5.         private int age;     //人的年龄
  6.         private char gender; //人的性别
  7.         public string Name       //下面是分别对三个字段的封装
  8.         {
  9.             get { return name; }
  10.             set { name = value; }
  11.         }
  12.         public int Age
  13.         {
  14.             get { return age; }
  15.             set { age = value; }
  16.         }
  17.         public char Gender
  18.         {
  19.             get { return gender; }
  20.             set { gender = value; }
  21.         }
  22.         public Person()//显示定义一个构造方法,避免继承的时候出现调用无参的方法时报错
  23.         { }
  24.         public Person(string name, int age, char gender)//有参构造方法,为了给参数赋值
  25.         {
  26.             this.name = name;
  27.             this.age = age;
  28.             this.gender = gender;
  29.         }
  30.         /// <summary>
  31.         /// 定义一个人打招呼的方法
  32.         /// </summary>
  33.         public virtual void SayHello()
  34.         {
  35.             Console.WriteLine("我是基类打招的方法");
  36.             Console.WriteLine("大家好,我叫{0},今年{1}岁,我是{2}生.", name, age, gender);
  37.         }
  38.     }
复制代码
  1. //Teacher类
  2.     class Teacher : Person
  3.     {
  4.         private int yearsofService;
  5.         public int YearsofService
  6.         {
  7.             get { return yearsofService; }
  8.             set { yearsofService = value; }
  9.         }
  10.         /// <summary>
  11.         /// Teacher的有参构造方法
  12.         /// </summary>
  13.         /// <param name="name">老师姓名</param>
  14.         /// <param name="age">老师年龄</param>
  15.         /// <param name="gender">老师性别</param>
  16.         /// <param name="yearsofService"></param>
  17.         public Teacher(string name, int age, char gender, int yearsofService)
  18.             : base(name, age, gender)
  19.         {
  20.             this.yearsofService = yearsofService;
  21.         }
  22.         /// <summary>
  23.         /// 定义一个老师的说话的方法
  24.         /// </summary>
  25.         public override void SayHello()
  26.         {
  27.             Console.WriteLine("我是父类打招呼的方法");
  28.             Console.WriteLine("大家好,我叫{0},今年{1},教书{2}年了.", Name, Age, yearsofService);
  29.         }
  30.     }
复制代码
  1. static void Main(string[] args)
  2.         {
  3.             Teacher t = new Teacher("焦", 12, '男', 12);
  4.             t.SayHello();
  5.             Console.ReadKey();
  6.         }
复制代码
我 又看了一下,想到了解决你的那个问题有两种,你看一下怎么样:1,就是我上面贴的代码,把你之前的Person类中SayHello()前的new关键字去掉,然后在子类Teacher的SayHello()方法前加new,这叫隐藏基类的方法,把子类中除了自己特有的字段外,父类的字段全部删除,可以输出想要的结果。2,就是把父类的方法前virtual或abstract,然后在子类的SayHello()方法前加override重载,也可以得到结果。完毕


评分

参与人数 1技术分 +1 收起 理由
czwanglei + 1

查看全部评分

回复 使用道具 举报
永远的小飞侠 发表于 2014-5-12 14:38
我 又看了一下,想到了解决你的那个问题有两种,你看一下怎么样:1,就是我上面贴的代码,把你之前的Pers ...

第一种方法可以,第二种方法不可以。
回复 使用道具 举报
czwanglei 发表于 2014-5-12 14:45
第一种方法可以,第二种方法不可以。
  1. abstract class Person
  2.     {
  3.         private string name;  //定义人的名字
  4.         private int age;     //人的年龄
  5.         private char gender; //人的性别
  6.         public string Name       //下面是分别对三个字段的封装
  7.         {
  8.             get { return name; }
  9.             set { name = value; }
  10.         }
  11.         public int Age
  12.         {
  13.             get { return age; }
  14.             set { age = value; }
  15.         }
  16.         public char Gender
  17.         {
  18.             get { return gender; }
  19.             set { gender = value; }
  20.         }
  21.         public Person()//显示定义一个构造方法,避免继承的时候出现调用无参的方法时报错
  22.         { }
  23.         public Person(string name, int age, char gender)//有参构造方法,为了给参数赋值
  24.         {
  25.             this.name = name;
  26.             this.age = age;
  27.             this.gender = gender;
  28.         }
  29.         /// <summary>
  30.         /// 定义一个人打招呼的方法
  31.         /// </summary>
  32.         public abstract void SayHello();
  33.         //{
  34.         //    //Console.WriteLine("我是基类打招的方法");
  35.         //    //Console.WriteLine("大家好,我叫{0},今年{1}岁,我是{2}生.", name, age, gender);
  36.         //}
  37.     }
复制代码
  1. class Teacher : Person
  2.     {
  3.         private int yearsofService;
  4.         public int YearsofService
  5.         {
  6.             get { return yearsofService; }
  7.             set { yearsofService = value; }
  8.         }
  9.         /// <summary>
  10.         /// Teacher的有参构造方法
  11.         /// </summary>
  12.         /// <param name="name">老师姓名</param>
  13.         /// <param name="age">老师年龄</param>
  14.         /// <param name="gender">老师性别</param>
  15.         /// <param name="yearsofService"></param>
  16.         public Teacher(string name, int age, char gender, int yearsofService)
  17.             : base(name, age, gender)
  18.         {
  19.             this.yearsofService = yearsofService;
  20.         }
  21.         /// <summary>
  22.         /// 定义一个老师的说话的方法
  23.         /// </summary>
  24.         public override void SayHello()
  25.         {
  26.             Console.WriteLine("我是父类打招呼的方法");
  27.             Console.WriteLine("大家好,我叫{0},今年{1},教书{2}年了.", Name, Age, yearsofService);
  28.         }
  29.     }
复制代码
  1. static void Main(string[] args)
  2.         {
  3.             Teacher t = new Teacher("焦", 12, '男', 12);
  4.             t.SayHello();
  5.             Console.ReadKey();
复制代码
不知道你说的不可以指的是 哪里不可以?我试了一下,第二种也是可以的吧,把Person类前加abstract为抽象类,父类中的SayHello()为抽象方法,子类不变,在SayHello()方法前加override,也可以得到结果。

评分

参与人数 1技术分 +2 收起 理由
czwanglei + 2

查看全部评分

回复 使用道具 举报
   版主....   我的问题已经改成结束好多天了....  为什么没有加分呢?   可能您忘了吧。链接:
http://bbs.itheima.com/forum.php ... peid%26typeid%3D384

回复 使用道具 举报
编了快两年的程序了这个星期开始看视频的时候,在写骑士飞行棋的时候终于习惯并且能合理的去调试程序了。
这次我用调试来看看这个程序的错误在哪里。
首先分析既然是SayHello这个方法的错误,那我先在调用这个方法的地方加个断点。
当程序执行到断点的时候我们用逐语句执行,注意不要用逐过程。
程序执行到这里的时候我们把需要输出的量加个监视看看它们的值有没有问题。
               这里我们发现,name和age的值都有问题,它们都不是我们在构造函数里设置的值。
所以可能是在构造函数了出了问题,我们就在调用构造函数的地方设个断点重新调试试试。
到了断点后用逐语句执行。
当我们运行到这里的时候 我们看下局部变量
这里我们终于发现了问题所在了,我们可以看到base的年龄等属性都被构造函数设置好了,但是我们发现Tearch的各各属性竟然还是没被设置?我们就去看看Tearch定义的时候的代码
class Teacher : Person
        {
            private string name;
            private int age;
            private char gender;
            private int yearsofService;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
            public int Age
            {
                get { return age; }
                set { age = value; }
            }
            public char Gender
            {
                get { return gender; }
                set { gender = value; }
            }

            public int YearsofService
            {
                get { return yearsofService; }
                set { yearsofService = value; }
            }
我们发现,他从Person类继承了,name,age等属性和字段后,又重新定义了这些字段和属性。看来这就是问题的所在了。我们把基类里有的那些东西删掉后我们再来运行下。
发现有错误,因为基类的name,age等是私有类型的。所以我们在父类的方法想要输出他们的值的话要用他们对应的属性。这样改完之后程序终于可以运行了。下面附上Teacher类的代码因为就这里改过了。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 论坛提问2
{
   
        //Teacher类
        class Teacher : Person
        {
           
            private int yearsofService;

            public int YearsofService
            {
                get { return yearsofService; }
                set { yearsofService = value; }
            }
            /// <summary>
            /// Teacher的有参构造方法
            /// </summary>
            /// <param name="name">老师姓名</param>
            /// <param name="age">老师年龄</param>
            /// <param name="gender">老师性别</param>
            /// <param name="yearsofService"></param>
            public Teacher(string name, int age, char gender, int yearsofService)
                : base(name, age, gender)
            {
                this.yearsofService = yearsofService;
            }
            /// <summary>
            /// 定义一个老师的说话的方法
            /// </summary>
            public void SayHello()
            {
                Console.WriteLine("我是父类打招呼的方法");
                Console.WriteLine("大家好,我叫{0},今年{1},教书{2}年了.", Name, Age, YearsofService);
            }
        }
    }

这里我用了调试的方法来找到了错误。其实这个错误对于学过继承方面知识的人来说相当的简单。可能一眼就看出来了。但是我这样做一方面是验证下我这3天学习的调试技巧的运用。另一方面如果是对继承的知识还不是理解的很透彻的人来说,只要有正确的调试技巧和思维。也可以发现我们的错误所在。

点评

不错,很详细  发表于 2014-5-15 13:47

评分

参与人数 1技术分 +2 收起 理由
czwanglei + 2

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马