通过基类来声明派生类有何意义?

时间:2022-09-08 09:09:37
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{    
    class Program
    { 
        static void Main()
        {
            MyBaseClass c = new MyDerivedClass();
                                
            Console.ReadLine();                       
        }
    }

    public class MyBaseClass
    {
        public void MethodOne()
        {            
        }
    }

    public class MyDerivedClass : MyBaseClass
    {
        public void MethodTwo()
        {
        }
    }
}


如上面的代码MyBaseClass是一个基类,MyDerivedClass是派生于MyBaseClass的一个类,
通过MyBaseClass声明一个MyDerivedClass的一个派生类c?
程序是允许这样做的,但这样做的意义何在?
为什么不能直接用MyDerivedClass派生类来声明呢?

13 个解决方案

#1


这就是多态的用法,虽然什么的是基类,但是由具体的子类去实现,所以如果有另一个模块,需要这样一个对象时,只需声明为基类,而不用关系到底是哪个子类

#2


开放封闭原则

#3


引用 1 楼 bdmh 的回复:
这就是多态的用法,虽然什么的是基类,但是由具体的子类去实现,所以如果有另一个模块,需要这样一个对象时,只需声明为基类,而不用关系到底是哪个子类


如果这种方法引用的话派生类中的方法不就使用不到了吗?
比如上面的例子,c只能引用MethodOne(),而不能引用MethodTwo()?

#4


引用 3 楼 sqn1982 的回复:
Quote: 引用 1 楼 bdmh 的回复:

这就是多态的用法,虽然什么的是基类,但是由具体的子类去实现,所以如果有另一个模块,需要这样一个对象时,只需声明为基类,而不用关系到底是哪个子类


如果这种方法引用的话派生类中的方法不就使用不到了吗?
比如上面的例子,c只能引用MethodOne(),而不能引用MethodTwo()?


一定要用的话,可以这么做
MyBaseClass c = new MyDerivedClass();
MyDerivedClass cc = c as MyDerivedClass;
cc.MethodTwo();
========================================
既然是基类声明,那么就只能用基类声明了的方法。
动物 a = new 鸟();
a.吃();//你可以这么写,因为我们知道a是动物,动物都能吃。
a.飞();//你不能这么写,因为我们 知道a是动物,然而并不是所有动物都能飞。
其实我认为更重要的是理解上的一种解决:我既然new的是一个人,那么我让这个对象做 能做的事,而不能让这个对象去做 男人才能做的事。

#5


这样写就能显得有意义了
abstract class BaseClass
{
      public abstract void Method();
}

class DerivedClass1
{
      public override void Method() { Console.WriteLine("This is DerivedClass1"); }
}

class DerivedClass2
{
      public override void Method() { Console.WriteLine("This is DerivedClass2"); }
}

class Worker
{
      public static void Add(BaseClass obj) { obj.Method(); }
}


使用时:
BaseClass obj1 = new DerivedClass1();
Worker.Add(obj1);
BaseClass obj2 = new DerivedClass2();
Worker.Add(obj2);

#6


C# 自带的一些函数 里面 很多参数都是使用的基类啊 
首先 基类有的属性和方法 子类是肯定有的 也就是说 子类毫无疑问的可以被当作基类来用
所以说 在一些函数中 比如 Graphics.DrawImage(Image ...) 中 使用的是 Image(基类) 作为参数 而不是子类 这样DrawImage函数 就能适应各种Image或者继承值Image的类了 因为DrawImage要的只是图像数据是一个Image对象都有的数据 所以说 那些继承至Image的类所多出来的那些细微区别 对于DrawImage而言 毫无意义 因为他要的只是图像数据然后绘制出来 如果说 DrawImage 的参数写死比如 他接受一个 Bitmap 类型 那么这个函数所能接受的参数范围 就大大降低了 虽然说可以直接强制转换DrawImage((Bitmap)img)这样之类的。。看着也会别扭吧。。。
也就是说 如果你关心的只是所有类的公共部分 而不是那些什么细微的区别 就用基类 因为他可以通用所有子类。。。

#8


引用 5 楼 shingoscar 的回复:
这样写就能显得有意义了
abstract class BaseClass
{
      public abstract void Method();
}

class DerivedClass1
{
      public override void Method() { Console.WriteLine("This is DerivedClass1"); }
}

class DerivedClass2
{
      public override void Method() { Console.WriteLine("This is DerivedClass2"); }
}

class Worker
{
      public static void Add(BaseClass obj) { obj.Method(); }
}


使用时:
BaseClass obj1 = new DerivedClass1();
Worker.Add(obj1);
BaseClass obj2 = new DerivedClass2();
Worker.Add(obj2);


你这个语法都错了,根本就没有实现继承!也就无从谈override 了!

#9


引用 8 楼 sqn1982 的回复:
Quote: 引用 5 楼 shingoscar 的回复:

这样写就能显得有意义了
abstract class BaseClass
{
      public abstract void Method();
}

class DerivedClass1
{
      public override void Method() { Console.WriteLine("This is DerivedClass1"); }
}

class DerivedClass2
{
      public override void Method() { Console.WriteLine("This is DerivedClass2"); }
}

class Worker
{
      public static void Add(BaseClass obj) { obj.Method(); }
}


使用时:
BaseClass obj1 = new DerivedClass1();
Worker.Add(obj1);
BaseClass obj2 = new DerivedClass2();
Worker.Add(obj2);


你这个语法都错了,根本就没有实现继承!也就无从谈override 了!

too yang...

#10


引用 8 楼 sqn1982 的回复:
你这个语法都错了,根本就没有实现继承!也就无从谈override 了!

直接打的,漏掉了: BaseClass

#11


引用 楼主 sqn1982 的回复:
如上面的代码MyBaseClass是一个基类,MyDerivedClass是派生于MyBaseClass的一个类,
通过MyBaseClass声明一个MyDerivedClass的一个派生类c?
程序是允许这样做的,但这样做的意义何在?
为什么不能直接用MyDerivedClass派生类来声明呢?


就编程而言,在 Main 方法中直接写
MyDerivedClass c = new MyDerivedClass();
显然更具体一些。因为一个MyDerivedClass对象它本身“就是”一个MyBaseClass对象,只要知道这个道理用在设计中,那么没有必要在代码上搞这个。

假设写代码的人想说变量c的类型其实是不确定的(也就是说,根本不确定MyDerivedClass实例,可能随后就要改为另外一种MyBaseClass子类实例),那么才应该暂时这样写。

而教程中给你这样写,最大的可能就像你说的“程序是允许这样做”而已,因此是一个给初学者教学的示范。

真正懂的抽象的人,反而不会胡乱抽象代码。如果可以使用具体类型,那么就尽量使用具体类型。我们在开发中自然是声明的类型(和接口)越少越好,代码写得越少越好。代码可以重构,而不是一开始就搞抽象的东西。

#12


初学者就好像是等待在围栏中等待喂食的家猪,它不去想围栏之外的野猪去想的事情。当一个变成教程告诉人一点点“设计的”知识时,理解起来就可能显得“困难”,而且写起来也困难。

就像这个例子一样,它没有真正告诉你为什么要多态,只能用一个枯燥的“程序是允许这样做的”的简单的一行代码的例子让你模仿。这时候就容易产生过分的想象空间。

#13


变成教程  -->  编程教程


很显然地,书上的这个例子设计得很不好,过于简单了。如果如邯郸学步一样去学了这个例子,就可能胡乱抽象。但是这可能也说明了,你看的这本书的面对的读者的素质不高。

#1


这就是多态的用法,虽然什么的是基类,但是由具体的子类去实现,所以如果有另一个模块,需要这样一个对象时,只需声明为基类,而不用关系到底是哪个子类

#2


开放封闭原则

#3


引用 1 楼 bdmh 的回复:
这就是多态的用法,虽然什么的是基类,但是由具体的子类去实现,所以如果有另一个模块,需要这样一个对象时,只需声明为基类,而不用关系到底是哪个子类


如果这种方法引用的话派生类中的方法不就使用不到了吗?
比如上面的例子,c只能引用MethodOne(),而不能引用MethodTwo()?

#4


引用 3 楼 sqn1982 的回复:
Quote: 引用 1 楼 bdmh 的回复:

这就是多态的用法,虽然什么的是基类,但是由具体的子类去实现,所以如果有另一个模块,需要这样一个对象时,只需声明为基类,而不用关系到底是哪个子类


如果这种方法引用的话派生类中的方法不就使用不到了吗?
比如上面的例子,c只能引用MethodOne(),而不能引用MethodTwo()?


一定要用的话,可以这么做
MyBaseClass c = new MyDerivedClass();
MyDerivedClass cc = c as MyDerivedClass;
cc.MethodTwo();
========================================
既然是基类声明,那么就只能用基类声明了的方法。
动物 a = new 鸟();
a.吃();//你可以这么写,因为我们知道a是动物,动物都能吃。
a.飞();//你不能这么写,因为我们 知道a是动物,然而并不是所有动物都能飞。
其实我认为更重要的是理解上的一种解决:我既然new的是一个人,那么我让这个对象做 能做的事,而不能让这个对象去做 男人才能做的事。

#5


这样写就能显得有意义了
abstract class BaseClass
{
      public abstract void Method();
}

class DerivedClass1
{
      public override void Method() { Console.WriteLine("This is DerivedClass1"); }
}

class DerivedClass2
{
      public override void Method() { Console.WriteLine("This is DerivedClass2"); }
}

class Worker
{
      public static void Add(BaseClass obj) { obj.Method(); }
}


使用时:
BaseClass obj1 = new DerivedClass1();
Worker.Add(obj1);
BaseClass obj2 = new DerivedClass2();
Worker.Add(obj2);

#6


C# 自带的一些函数 里面 很多参数都是使用的基类啊 
首先 基类有的属性和方法 子类是肯定有的 也就是说 子类毫无疑问的可以被当作基类来用
所以说 在一些函数中 比如 Graphics.DrawImage(Image ...) 中 使用的是 Image(基类) 作为参数 而不是子类 这样DrawImage函数 就能适应各种Image或者继承值Image的类了 因为DrawImage要的只是图像数据是一个Image对象都有的数据 所以说 那些继承至Image的类所多出来的那些细微区别 对于DrawImage而言 毫无意义 因为他要的只是图像数据然后绘制出来 如果说 DrawImage 的参数写死比如 他接受一个 Bitmap 类型 那么这个函数所能接受的参数范围 就大大降低了 虽然说可以直接强制转换DrawImage((Bitmap)img)这样之类的。。看着也会别扭吧。。。
也就是说 如果你关心的只是所有类的公共部分 而不是那些什么细微的区别 就用基类 因为他可以通用所有子类。。。

#7


#8


引用 5 楼 shingoscar 的回复:
这样写就能显得有意义了
abstract class BaseClass
{
      public abstract void Method();
}

class DerivedClass1
{
      public override void Method() { Console.WriteLine("This is DerivedClass1"); }
}

class DerivedClass2
{
      public override void Method() { Console.WriteLine("This is DerivedClass2"); }
}

class Worker
{
      public static void Add(BaseClass obj) { obj.Method(); }
}


使用时:
BaseClass obj1 = new DerivedClass1();
Worker.Add(obj1);
BaseClass obj2 = new DerivedClass2();
Worker.Add(obj2);


你这个语法都错了,根本就没有实现继承!也就无从谈override 了!

#9


引用 8 楼 sqn1982 的回复:
Quote: 引用 5 楼 shingoscar 的回复:

这样写就能显得有意义了
abstract class BaseClass
{
      public abstract void Method();
}

class DerivedClass1
{
      public override void Method() { Console.WriteLine("This is DerivedClass1"); }
}

class DerivedClass2
{
      public override void Method() { Console.WriteLine("This is DerivedClass2"); }
}

class Worker
{
      public static void Add(BaseClass obj) { obj.Method(); }
}


使用时:
BaseClass obj1 = new DerivedClass1();
Worker.Add(obj1);
BaseClass obj2 = new DerivedClass2();
Worker.Add(obj2);


你这个语法都错了,根本就没有实现继承!也就无从谈override 了!

too yang...

#10


引用 8 楼 sqn1982 的回复:
你这个语法都错了,根本就没有实现继承!也就无从谈override 了!

直接打的,漏掉了: BaseClass

#11


引用 楼主 sqn1982 的回复:
如上面的代码MyBaseClass是一个基类,MyDerivedClass是派生于MyBaseClass的一个类,
通过MyBaseClass声明一个MyDerivedClass的一个派生类c?
程序是允许这样做的,但这样做的意义何在?
为什么不能直接用MyDerivedClass派生类来声明呢?


就编程而言,在 Main 方法中直接写
MyDerivedClass c = new MyDerivedClass();
显然更具体一些。因为一个MyDerivedClass对象它本身“就是”一个MyBaseClass对象,只要知道这个道理用在设计中,那么没有必要在代码上搞这个。

假设写代码的人想说变量c的类型其实是不确定的(也就是说,根本不确定MyDerivedClass实例,可能随后就要改为另外一种MyBaseClass子类实例),那么才应该暂时这样写。

而教程中给你这样写,最大的可能就像你说的“程序是允许这样做”而已,因此是一个给初学者教学的示范。

真正懂的抽象的人,反而不会胡乱抽象代码。如果可以使用具体类型,那么就尽量使用具体类型。我们在开发中自然是声明的类型(和接口)越少越好,代码写得越少越好。代码可以重构,而不是一开始就搞抽象的东西。

#12


初学者就好像是等待在围栏中等待喂食的家猪,它不去想围栏之外的野猪去想的事情。当一个变成教程告诉人一点点“设计的”知识时,理解起来就可能显得“困难”,而且写起来也困难。

就像这个例子一样,它没有真正告诉你为什么要多态,只能用一个枯燥的“程序是允许这样做的”的简单的一行代码的例子让你模仿。这时候就容易产生过分的想象空间。

#13


变成教程  -->  编程教程


很显然地,书上的这个例子设计得很不好,过于简单了。如果如邯郸学步一样去学了这个例子,就可能胡乱抽象。但是这可能也说明了,你看的这本书的面对的读者的素质不高。