子类、父类和实例类的模糊点

li365941471 2011-10-14 03:02:17

public class MyParent//父类
{
public void writeLine()
{
MyChildren cc = new MyChildren();

//print(); //--------------------------------这个地方是肯定没法调用的!!!!!为什么????????
//
/*
* 既然Children是Parent的子类,那么应该是先有父亲,再有儿子,对吧?
* 那么父亲要编绎成功了,儿子才能编绎成功,是不?也就是说你先把儿子杀了(删掉该文件),
* 你去编绎父亲,看你能编绎成功不?
*/

cc.print("aa"); //正确。调用子类的print方法,没有任何意义。
//cc.pring(); //出错,为什么?因为(出了自己类的声明范围,在外界(实例此类的对象)就只能发能调用public的方法了)
}

protected void MyParentMethod()
{

}
}
public class MyChildren : MyParent//子类
{
protected void print()
{
MyParentMethod(); //正确,子类继承父类,可以使用任何父类非private方法
writeLine(); //正确,子类继承父类,可以使用任何父类非private方法

}

public void print(string str)
{
MyParent p = new MyParent();
p.writeLine(); //正确。
//p.MyParentMethod() //出错(出了自己类的声明范围,在外界(实例此类的对象)就只能发能调用.
}
}

public class MyTestClass //无关类
{
MyParent p = new MyParent();
public void test()
{
p.writeLine(); //正确
//p.MyParent(); //出错(出了自己类的声明范围,在外界(实例此类的对象)就只能发能调用public的方法了)
}
}



老鸟飘过~~~
初学的朋友没弄懂的可以结合自己的理解看一下。。。
这东西困扰了我很久啊。。。

...全文
207 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
li365941471 2011-10-15
  • 打赏
  • 举报
回复
[Quote=引用 39 楼 mrlen 的回复:]
擦……原因还不简单吗?


你这个有点象“老爸想让别人家的儿子来抚养自己……”
[/Quote]

嘿嘿,弄明白了,一眼就看出问题。没弄懂,就一直困扰额。。
颤菊大师 2011-10-14
  • 打赏
  • 举报
回复
擦……原因还不简单吗?


你这个有点象“老爸想让别人家的儿子来抚养自己……”
b_duan 2011-10-14
  • 打赏
  • 举报
回复
学习学习,交互中才有提高。
li365941471 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 35 楼 caozhy 的回复:]
[/Quote]

受教了。
li365941471 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 35 楼 caozhy 的回复:]
比如说大象是哺乳动物

大象类继承了哺乳动物类

我说那只大象在给幼仔哺乳,和我说那只哺乳动物在给幼仔哺乳。是一回事。
而不是大象体内还住着一个哺乳动物。大象利用身上叫哺乳动物的那一块来哺乳。
[/Quote]

这个比方很精典啊,高人就是高人啊。
threenewbee 2011-10-14
  • 打赏
  • 举报
回复
比如说大象是哺乳动物

大象类继承了哺乳动物类

我说那只大象在给幼仔哺乳,和我说那只哺乳动物在给幼仔哺乳。是一回事。
而不是大象体内还住着一个哺乳动物。大象利用身上叫哺乳动物的那一块来哺乳。


如果一个protected类型可以被同类型的其它对象访问。那么我完全可以把它当作public使。只要继承一个这个类型,获取值,通过一个共有方法传出去就可以了(看如下代码)。那还有要protected的必要么?

class A
{
protected int i = 10;
}
Main()
{
A a = new A();
int x = a.i; //不可以,我们绕一下:加上B类定义,再用下面一行。
int x = new B().GetI(a);
}
class B : A //这个类专门用于获得i
{
public int GetI(A a)
{
return a.i;
}
}
li365941471 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 33 楼 caozhy 的回复:]
引用 31 楼 li365941471 的回复:
anotherHome是局部对象怎么能访问全局变量?

哪里来的全局变量?你还是什么也没有理解。。。

算了,不说了。要想完全理解,不是几句话说清楚的。

比喻可以帮助理解,但是,比喻也有比喻不到的地方。所以比喻不能代替理解。
[/Quote]
看错了。public void GetMoney(Home anotherHome)
我以为是另外一个类。

好吧,我承认我错了。。。。结贴,潜水。。
threenewbee 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 li365941471 的回复:]
anotherHome是局部对象怎么能访问全局变量?
[/Quote]
哪里来的全局变量?你还是什么也没有理解。。。

算了,不说了。要想完全理解,不是几句话说清楚的。

比喻可以帮助理解,但是,比喻也有比喻不到的地方。所以比喻不能代替理解。
threenewbee 2011-10-14
  • 打赏
  • 举报
回复
父亲儿子的比喻根本就是错的。

实际上,B继承了A,那么B就是A。B是B,也是A。只有一个对象,而不是2个。

但是你不能说儿子继承了父亲,因而儿子既是儿子也是父亲。
li365941471 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 caozhy 的回复:]
比如


C# code

class Home
{
private int money = 1000;
public void GetMoney(Home anotherHome)
{
Console.WriteLine(this.money); // 可以,this.money 可以简写 money
Consol……
[/Quote]

anotherHome是局部对象怎么能访问全局变量?
threenewbee 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 li365941471 的回复:]
/*
* 既然Children是Parent的子类,那么应该是先有父亲,再有儿子,对吧?
* 那么父亲要编绎成功了,儿子才能编绎成功,是不?也就是说你先把儿子杀了(删掉该文件),
* 你去编绎父亲,看你能编绎成功不?
*/
[/Quote]
你根本就没有理解。你的解释都是错的。
看这样的代码:
class A
{
public void foo()
{
B b = this as B;
if (b != null) b.print();
}
}
class B : A
{
public void print() { ... }
}
Main()
{
A a = new B();
a.foo();
}

用你的理论怎么解释呢?
li365941471 2011-10-14
  • 打赏
  • 举报
回复
呵呵,可能我描述不清楚吧,不过 hztltgg(我想我是风) 明白了我的意思,同时很高兴和
caozhy(cfx) 的交谈,虽然谈得不是我这个问题了,但是还是感觉受益匪浅,只是我执着于
我这个问题上面去了。呵呵,感谢caozhy(cfx)
threenewbee 2011-10-14
  • 打赏
  • 举报
回复
比如

class Home
{
private int money = 1000;
public void GetMoney(Home anotherHome)
{
Console.WriteLine(this.money); // 可以,this.money 可以简写 money
Console.WriteLine(anotherHome.money); // 不可以
}
}
threenewbee 2011-10-14
  • 打赏
  • 举报
回复
我说得很清楚了,不知道你哪里不理解。我猜测,要么
(1)
你没有理解继承,一旦一个类继承了另一个类,那么它自己就已经是基类了,而不需要实例化一个变量。
(2)
你没有理解可见性的含义。比如说private,私有的,什么意思?就是类内部可以访问,外部不可以访问。
比如说,家里的存款,对于家庭成员这个类来说,是私有的。你可以访问,我不可以访问。
但是,不是说,家里的存款,“家庭成员”都可以访问。我是我家的家庭成员,也可以访问你家的存款。
li365941471 2011-10-14
  • 打赏
  • 举报
回复
//print(); //--------------------------------这个地方是肯定没法调用的!!!!!为什么????????
根本没有print()这个方法。
假设你想调用,也是child.print()

是的,所以我下面写了注释。我告诉人家这里不能这么用,因为可能会有人在上面纠结
/*
* 既然Children是Parent的子类,那么应该是先有父亲,再有儿子,对吧?
* 那么父亲要编绎成功了,儿子才能编绎成功,是不?也就是说你先把儿子杀了(删掉该文件),
* 你去编绎父亲,看你能编绎成功不?
*/


(2)
public void test()
{
p.writeLine(); //正确
//p.MyParent(); //出错(出了自己类的声明范围,在外界(实例此类的对象)就只能发能调用public的方法了)
}
p.MyParent(); 这是什么意思?有这个方法么?你是要实例化一个对象还是调用方法?


这是两个不相关的类,我既然实例化了MyParent了,为什么不能调用他得方法呢?
li365941471 2011-10-14
  • 打赏
  • 举报
回复

public class MyTestClass //无关类
{
MyParent p = new MyParent();
public void test()
{
p.writeLine(); //正确
//p.MyParent(); //出错(出了自己类的声明范围,在外界(实例此类的对象)就只能发能调用public的方法了)
}
}



就好像这段,他得重点在哪?重点就是p为什么不能调用自身的protected方法
因为(出了自己类的声明范围,在外界(实例此类的对象)就只能发能调用public的方法了)
以前我不知道,现在知道了,同样肯定也会有现在还不知道的人吧。
threenewbee 2011-10-14
  • 打赏
  • 举报
回复
当然了,你可能说,都调用就是了。

但是问题来了

如果有这么个函数

class A
{
void foo() { bool result = child.print(); } //这里得到true好呢,还是false好呢?
}
class B : A
{
public bool print() { return false; }
}
class C : A
{
public bool print() { return true; }
}

threenewbee 2011-10-14
  • 打赏
  • 举报
回复
你的代码写得很不合规矩,即便你认为你的代码有道理,也至少从语法上要和C#本身的约定一致。
比如(1)
//print(); //--------------------------------这个地方是肯定没法调用的!!!!!为什么????????

根本没有print()这个方法。
假设你想调用,也是child.print()

但是我问你,如果你是C#的设计者,你需要给编译器加上这个功能。

那么

class A
{
void foo() { child.print(); } //这里调用 b.print() 还是 c.print() 呢?}
class B : A
{
public void print() { ... }
}
class C : A
{
public void print() { ... }
}


(2)
public void test()
{
p.writeLine(); //正确
//p.MyParent(); //出错(出了自己类的声明范围,在外界(实例此类的对象)就只能发能调用public的方法了)
}
p.MyParent(); 这是什么意思?有这个方法么?你是要实例化一个对象还是调用方法?
li365941471 2011-10-14
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 hztltgg 的回复:]
父类子类继承,这个概念一开始就约定的不好,应该是泛化关系,特殊一般关系。
父类子类给人一个实例的概念,父亲和儿子,都是实例,而继承本质上类的概念,如

鱼妈妈,鱼宝宝。
鱼,鲤鱼。

,如果理解了继承是下面这些关系,而不是上面这种,就会不去new父类了,鱼定义了吃,鲤鱼自然而然也就直接能吃了,而鱼妈妈定义了吃,鱼宝宝能不能吃?

====
protected 就是受保护的意思,你……
[/Quote]
是的,只是以前没理解,而且机械性的去用new来为继承做事,实在很傻。。关键就是在这里:我就是怕有和我一样困扰在这个地方的初学者,既然弄懂了,就发出来给他们看看。
threenewbee 2011-10-14
  • 打赏
  • 举报
回复
protected和public、private是一样的。
只不过public修饰的成员类的外部可以看到,而private修饰的成员,子类也看不到。
加载更多回复(20)
Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型? Overload是重载的意思,Override是覆盖的意思,也就是重写。 重载Overload表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同)。 重写Override表示类中的方法可以与类中的某个方法的名称和参数完全相同,通过类创建的实例对象调用这个方法时,将调用类中的定义方法,这相当于把类中定义的那个完全相同的方法给覆盖了,这也是面向对象编程的多态性的一种表现。类覆盖类的方法时,只能比类抛出更少的异常,或者是抛出类抛出的异常的异常,因为类可以解决类的一些问题,不能比类有更多的问题。类方法的访问权限只能比类的更大,不能更小。如果类的方法是private类型,那么,类则不存在覆盖的限制,相当于类中增加了一个全新的方法。 至于Overloaded的方法是否可以改变返回值的类型这个问题,要看你倒底想问什么呢?这个题目很模糊。如果几个Overloaded的方法的参数列表不一样,它们的返回者类型当然也可以不一样。但我估计你想问的问题是:如果两个方法的参数列表完全一样,是否可以让它们的返回值不同来实现重载Overload。这是不行的,我们可以用反证法来说明这个问题,因为我们有时候调用一个方法时也可以不定义返回结果变量,即不要关心其返回结果,例如,我们调用map.remove(key)方法时,虽然remove方法有返回值,但是我们通常都不会定义接收返回结果的变量,这时候假设该类中有两个名称和参数列表完全相同的方法,仅仅是返回类型不同,java就无法确定编程者倒底是想调用哪个方法了,因为它无法通过返回结果类型来判断。 override可以翻译为覆盖,从字面就可以知道,它是覆盖了一个方法并且对其重写,以求达到不同的作用。对我们来说最熟悉的覆盖就是对接口方法的实现,在接口中一般只是对方法进行了声明,而我们在实现时,就需要实现接口声明的所有方法。除了这个典型的用法以外,我们在继承中也可能会在类覆盖类中的方法。在覆盖要注意以下的几点: 1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果; 2、覆盖的方法的返回值必须和被覆盖的方法的返回一致; 3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其类; 4、被覆盖的方法不能为private,否则在其类中只是新定义了一个方法,并没有对其进行覆盖。 overload对我们来说可能比较熟悉,可以翻译为重载,它是指我们可以定义一些名称相同的方法,通过定义不同的输入参数来区分这些方法,然后再调用时,VM就会根据不同的参数样式,来选择合适的方法执行。在使用重载要注意以下的几点: 1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int,float),但是不能为fun(int,int)); 2、不能通过访问权限、返回类型、抛出的异常进行重载; 3、方法的异常类型和数目不会对重载造成影响; 4、对于继承来说,如果某一方法在类中是访问权限是priavte,那么就不能在类对其进行重载,如果定义的话,也只是定义了一个新方法,而不会达到重载的效果。

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧