传递参数类型时该如何处理

ztmsimon 2018-03-05 05:14:21
我想使用一个接口,每个继承此接口的类的传入的参数类型不同,此时该如何处理为好啊?



public interface IComm
{
bool IConn(c);
}

public class ComConfig
{
public int p;
public int timeout;
}
public class Com :IComm
{
public bool IConn(ComConfig c)
{
return true;
}
}

public class LanConfig
{
public string ip;
public int port;
}
public class Lan : IComm
{
public bool IConn(LanConfig c)
{
return true;
}
}


之前我是想使用泛型来处理,但是好像也不行,我觉得应该有方法实现吧?
请各位大神帮帮忙!

...全文
873 47 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
47 条回复
切换为时间正序
请发表友善的回复…
发表回复
正怒月神 2018-03-08
  • 打赏
  • 举报
回复
引用 46 楼 ztmsimon 的回复:
[quote=引用 45 楼 sp1234 的回复:] 再重申一下面向对象技术跟结构化技术的根本差别吧,实际上有的人就是不理解:“为什么子类继承于父类、又要重写和对消掉父类的某些内部特性?”,理解了这一点你就理解了面向对象。不理解这一点,而只能理解前一半,那么尽管使用OOPL语言,满口地说着“继承、接口、抽象”等等,也还是仅仅是结构化思维方式。
嗯,我觉得这个说到点上去了,我感觉我就是一直在这里遇到了瓶颈,一直想着如何封装,想将所有的子类全部写的相同(接口上的,非内部实现上),那么给别人调用的时候就十分方便,可能是这种想法有点走火入魔了...到了继承以及多态的时候,有时候不知道该如何把握。 [/quote] 不要尝试过度封装,把相同行为拿出来抽象就好了。
ztmsimon 2018-03-08
  • 打赏
  • 举报
回复
引用 45 楼 sp1234 的回复:
再重申一下面向对象技术跟结构化技术的根本差别吧,实际上有的人就是不理解:“为什么子类继承于父类、又要重写和对消掉父类的某些内部特性?”,理解了这一点你就理解了面向对象。不理解这一点,而只能理解前一半,那么尽管使用OOPL语言,满口地说着“继承、接口、抽象”等等,也还是仅仅是结构化思维方式。
嗯,我觉得这个说到点上去了,我感觉我就是一直在这里遇到了瓶颈,一直想着如何封装,想将所有的子类全部写的相同(接口上的,非内部实现上),那么给别人调用的时候就十分方便,可能是这种想法有点走火入魔了...到了继承以及多态的时候,有时候不知道该如何把握。
流星亚瑟 2018-03-07
  • 打赏
  • 举报
回复
看了半天感觉楼主应该从调用者职责角度来考虑 建议通过以下思路明确: 假设我的理解是对 的:调用者需要调用IComm对象的Conn()方法,实现连接操作。 那么回答以下问题: 调用者负责指定连接的类型 么? (usb/lan/com) 建议用一个工厂类好了,ICommFactory.GetComm();

public class CommFactory{
    public IComm GetComm()
    {
        //根据配置返回IComm对象
    }

    public IComm GetComm(CommType type)
    {
        //根据type返回IComm对象
    }
}
连接时需要负责指定其配置么?(是否有对同一个IComm对象转换不同配置的业务场景?) 如果不需要,让每个接口实现类自行loadconfig 好了 如果需要:那么 调用者需要关心配置的细节么?(是否这些配置已经固化下来了?) 如果已经固化了,可以

public interface IComm
    {
        bool IConn(string configName);
    }
   public class Com :IComm
    {      
        public bool IConn(string configName) 
        {
            //load Com config by configName
            return true;        
        }    
    }
    public class Lan : IComm
    {
        public bool IConn(string configName)
        {
            //load Lan config by configName
            return true;
        }
    }
如果没有固化,调用者可以随意指定config细节并对其执行结果负责,那么抽象成接口的必要性就值得商槯了 总之,你大可找个调用者代码的开发人来讨论,看看两边愿意承担多少责任,抽象的粒度也就出来了
  • 打赏
  • 举报
回复
interface IConn
{
    void Connect();
}
正因为不能在父类定义所谓差别,而父类又需要有一个 Connect 操作,所以这里不应该纠结什么参数。各个子类扩展中会定义它自己的 this.XXXXX 这样的参数,并非用 Connect 方法参数来实现。 你再好好重温一下上面这些设计概念。
  • 打赏
  • 举报
回复
再重申一下面向对象技术跟结构化技术的根本差别吧,实际上有的人就是不理解:“为什么子类继承于父类、又要重写和对消掉父类的某些内部特性?”,理解了这一点你就理解了面向对象。不理解这一点,而只能理解前一半,那么尽管使用OOPL语言,满口地说着“继承、接口、抽象”等等,也还是仅仅是结构化思维方式。
  • 打赏
  • 举报
回复
引用 36 楼 ztmsimon 的回复:
[quote=引用 35 楼 xuzuning 的回复:] 是的,每种方式都有不同的参数和行为,否则就不能称为独立的方式 但这些都是专属于这个方式的特征,是个性化的东西,所以他们就应被隐藏在方式的实现代码(配置文件)中 不如此,就不能以统一的面貌示人
我是将这些配置的信息放入数据库中。 我是看还能否抽象一层,将不同的配置也放入一个接口或者whatever之中,这样做到在代码级别的不修改,只修改配置。 [/quote] 配置里边的字符串不管怎么写,那么读取配置信息的程序代码也是在子类中定义各种实现的。比如说
interface IConfig
{
    void Connect();
}
这样 Comm 实现自己的 Connect 方法,而 Lan 则实现完全不同的 Connect 方法。也就是说,父类的某处具体实现的差别定义在子类,而不是父类。 而你说的所谓父类就实现好一个万能Connect类而仅仅靠“传入的参数类型不同”来做到万能,那是万万不能的,是根本就不符合最基本、很容理解的面向对象继承概念的。
流星亚瑟 2018-03-07
  • 打赏
  • 举报
回复
引用 39 楼 ztmsimon 的回复:
调用者也是通过数据库的配置来识别。 比如在数据库中设置通信方式,只能在3种中选择一种,比如选择了com进行通信,那在配置中就需要配置com口号,波特率等等信息,如果选择了lan,配置中也会配置好对应的ip跟port。 隐隐约约感觉在建立连接这里能处理一下。现在我的做法是将所有通信类对应的配置全部放入了一个类中。
加个工厂,预定义配置 name,那么代码大概可以这样

public class CommFactory{
 
    public IComm GetComm(string configName) // or define enum
    {
        IComm comm;
        //Load Comm Type by config name
       //select commType, configData form CommConfigTable
        if (commType = "com") { 
            var com = new Com(); 
            //Build com config 
            com.port = 2;

            comm = com;
        }
        if (commType = "lan"){
    
           var lan = new Lan(); 
            //Build lan config 
            lan.url = "http://someurl";

            comm = lan
        }
        return comm;
    }
}
config name 甚至可以更进一步,使用连接端的名字,比如 谷歌/百度... 那么调用者仅关心需要和谁连接,而不需要关心通过什么类型连接,更不必关心具体什么配置参数
xuzuning 2018-03-07
  • 打赏
  • 举报
回复
为什么你就绕不过这个弯呢? 你可以在 (usb/lan/com) 实例化时进行配置,也可以在 (usb/lan/com)实例化后进行配置 配置信息可以存放在媒介中,也可以直接写在代码中 只是,如果你选择了实例化后配置的话,那么需要抽象出执行配置的方法到 父类或接口 无论如何,都不会出现你主贴中的不定类型传递的问题
闭包客 2018-03-07
  • 打赏
  • 举报
回复
泛型也好,委托也好,都是处理这种问题的一种思路,但前提是继承接口的类要有可以抽象出来的共性。
ztmsimon 2018-03-07
  • 打赏
  • 举报
回复
引用 38 楼 awcyy 的回复:
看了半天感觉楼主应该从调用者职责角度来考虑 建议通过以下思路明确: 假设我的理解是对 的:调用者需要调用IComm对象的Conn()方法,实现连接操作。 那么回答以下问题: 调用者负责指定连接的类型 么? (usb/lan/com) 连接时需要负责指定其配置么?(是否有对同一个IComm对象转换不同配置的业务场景?) 如果不需要,让每个接口实现类自行loadconfig 好了 如果需要:那么 调用者需要关心配置的细节么?(是否这些配置已经固化下来了?) 如果没有固化,调用者可以随意指定config细节并对其执行结果负责,那么抽象成接口的必要性就值得商槯了 总之,你大可找个调用者代码的开发人来讨论,看看两边愿意承担多少责任,抽象的粒度也就出来了
调用者也是通过数据库的配置来识别。 比如在数据库中设置通信方式,只能在3种中选择一种,比如选择了com进行通信,那在配置中就需要配置com口号,波特率等等信息,如果选择了lan,配置中也会配置好对应的ip跟port。 隐隐约约感觉在建立连接这里能处理一下。现在我的做法是将所有通信类对应的配置全部放入了一个类中。
  • 打赏
  • 举报
回复
引用 31 楼 ztmsimon 的回复:
对我来说,这个new里面应该是三个参数:tcp,ip,port。 在这里全部整合成一个string,而且使用//或者:的连接方式。 我就是不想让调用者这样使用。要不然我就可以统一使用string来传递参数了... 我是希望调用者只在我限定的范围类传递参数。
这正是我说的“镜中的头”的例子。 你说的这个 new 是子类特性,例如
IDevice x = new Comm(2);
或者
IDevice x = new Comm();
var y = (Comm)x;
y.Port = 2;
或者
var x = new Comm();
x.Port = 2;
(IDevice)x.Port =1;
总之,调用者知道细节。而你的“限定的范围”是说父类(父接口)不是规定父协议,反而是父类要实现所有子类的“限定”,这说明你从根本上就没有理解面向对象能做什么、不能做什么。
  • 打赏
  • 举报
回复
上面Comm举例代码改一下
IDevice x = new Comm();
(Comm)x.Port = 2;
.....
x.设备某方法();
或者写[code=csharp]var x = new Comm(); x.Port = 2; ..... x.设备某方法();[ 直接可以把 x 用在各种针对 IDevice 的多态操作中/code]
ztmsimon 2018-03-06
  • 打赏
  • 举报
回复
引用 29 楼 sp1234 的回复:
调用者知道细节,所以他写下这样的代码
IDevice x = new lan("tcp://189.1.2.3:8676");
你正好相反,你说写下这段代码的程序员不知道子类细节,而实现(可能是1年前开发出来的) Device 父类却能够知道将来所有扩展子类的细节。
对我来说,这个new里面应该是三个参数:tcp,ip,port。 在这里全部整合成一个string,而且使用//或者:的连接方式。 我就是不想让调用者这样使用。要不然我就可以统一使用string来传递参数了... 我是希望调用者只在我限定的范围类传递参数。
  • 打赏
  • 举报
回复
iDevice 可以定义了“设备某方法”的需求,这个完全可以理解。但是如果你此时纠结它“知道子类的参数”,这就是好像你爱上了如镜中的头而要割掉自己脖子上的头一样荒谬了。 再次说明一遍,Device中 既然不能确定参数,那么就不使用参数,或者顶多是 abstract 的特性。没有什么万能的代码能“又圆又方”,这里越是简单的道理越需要花几年时间才能理解。
ztmsimon 2018-03-06
  • 打赏
  • 举报
回复
引用 25 楼 xuzuning 的回复:
public interface I通讯 bool 发送(string 命令); } public class 串口 : I通讯 { } public class usb : I通讯 { } public class lan : I通讯 { } //于是,使用串口就 I通讯 comm = new 串口(); comm 发送("12345"); //使用 usb 就 comm = new usb(); comm 发送("12345"); //使用 lan 就 comm = new lan(); comm 发送("12345"); 并不会出现你所谓的冲突问题 面向对象的设计原则就是公开共性、隐藏个性
comm = new lan();的时候,不是无参的,每种方式所需参数是不同的。
  • 打赏
  • 举报
回复
引用 27 楼 ztmsimon 的回复:
comm = new lan();的时候,不是无参的,每种方式所需参数是不同的。
调用者知道细节,所以他写下这样的代码
IDevice x = new lan("tcp://189.1.2.3:8676");
你正好相反,你说写下这段代码的程序员不知道子类细节,而实现(可能是1年前开发出来的) Device 父类却能够知道将来所有扩展子类的细节。
  • 打赏
  • 举报
回复
lz又不想把所有东西都写成运行时反射代码,又想要动态
引用 21 楼 ztmsimon 的回复:
[quote=引用 20 楼 xuzuning 的回复:] 分别给 串口、usb、lan 定义一个类,并让这些类都去实现一个接口。 程序中,你实际传递和操作的是那个接口,从而达到统一的目的
我就是使用接口在这样做啊。 但是创建的时候需要的参数不同。需要的参数数量不同,参数类型也不同。[/quote] 在 #6 楼已经给你写代码了。再给你写一遍,例如
public class Lan: IDevice, ILanConnect, ILanConfig
{
    public void 设备某方法()
    {
    .....使用 this.IP 等等来实现 Conn特殊定义
    }
}
 
public class Comm: IDevice, ICommConnect, ICommConfig
{
    public void 设备某方法()
    {
    .....使用 this.Port 等等来实现 Conn特殊定义
    }
}
那么你自然可以写
IDevice x = new Comm();
x.Port = 2;
.....
x.设备某方法();
    
你还可以为 Comm 单独定义一个实例化方法来把 Port 等参数封装进去。 关键在于,各个子类独特的特性自然是定义在子类(子接口)上的,为什么纠结到什么父类(父接口)那里去呢?
xuzuning 2018-03-06
  • 打赏
  • 举报
回复
public interface I通讯 bool 发送(string 命令); } public class 串口 : I通讯 { } public class usb : I通讯 { } public class lan : I通讯 { } //于是,使用串口就 I通讯 comm = new 串口(); comm 发送("12345"); //使用 usb 就 comm = new usb(); comm 发送("12345"); //使用 lan 就 comm = new lan(); comm 发送("12345"); 并不会出现你所谓的冲突问题 面向对象的设计原则就是公开共性、隐藏个性
  • 打赏
  • 举报
回复
你在世界上找不到一个“又圆又方的屋顶”,那种屋顶听上去挺唬人,但是放到工作中是不具有现实行动力的。
  • 打赏
  • 举报
回复
object 其实并不能说明具体的含义,所以 lz 就自己办自己搞懵了。他觉得一定有又跟 object 一样,又完全解决了 object 问题的新鲜的代码写法。
加载更多回复(26)

111,098

社区成员

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

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

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