草庐IT

types - 无开销的开关接口(interface)实现

coder 2023-06-26 原文

给定一个接口(interface)和两个(或更多)实现,我很难在扩展功能时轻松切换实现。

例如,假设有一个支持 Inc 和 String 的接口(interface) INumber 以及两个实现 NumberInt32 和 NumberInt64 及其明显的实现。假设我想在 INumber 之上实现一个 EvenCounter。 EvenCounter 只有一个 IncTwice 并且应该调用 Inc 两次。如果不在 EvenCounter 中的 INumber 周围使用额外的结构,我很难获得正确的类型。

type INumber interface {
    Inc() 
    String() string
}

type NumberInt32 struct {
    number int32
}

func NewNumberInt32() INumber {
    ret := new(NumberInt32)
    ret.number = 0
    return ret
}

func (this *NumberInt32) Inc() { 
    this.number += 1
}

func (this *NumberInt32) String() string {
    return fmt.Sprintf("%d", this.number)
}

// type NumberInt64.... // obvious

这是我奋斗的地方

type EvenCounter1 INumber // nope, additional methods not possible 
type EvenCounter2 NumberInt32 // nope
func (this *EvenCounter2) IncTwice() {  
for i:=0; i < 2; i+=1 {
    // this.Inc() // Inc not found
    // INumber(*this).Inc() // cannot convert       
    // in, ok := *this.(INumber) // cannot convert
    // v, ok := this.(INumber) // cannot convert
    // a concrete conversion a) does not work and b) won't help
    // here it should be generic
    // v, ok := this.(NumberInt32) 
    // How do I call Inc here on this?
    }
}

只需嵌入到一个结构中就可以了...

type EvenCounter3 struct {
    n INumber
}

func (this *EvenCounter3) IncTwice() {
    n := this.n // that is a step I want to avoid
    n.Inc() // using this.n.Inc() twice makes it slower
    n.Inc()
}

func (this *EvenCounter3) String() string {
    return this.n.String()
}

我可以忍受为每个方法手动实现委托(delegate)的需要,但是 显然我想依赖 INumber 而不是具体的实现(即 将意味着改变很多地方来尝试另一种实现,但是,我想避免额外的间接访问和(很可能?)额外的空间。有没有 避免结构并直接说 EvenCounter 是具有其他方法的(特定)INumber 的方法?

顺便说一下,真实的例子是一组整数和一个整数到整数的映射,其中有数百万个实例相互交织(不,仅仅 map[int]bool 是不够的——太慢了,bitset 很有趣,具体取决于用例等)并通过更改代码中的 2-3 行轻松测试集合和映射的不同实现(理想情况下只是类型,也许 实例的通用创建。复制)

感谢任何帮助,我希望这还没有被问到......

最佳答案

您使用嵌入的变体实际上并未嵌入。 Embedded fields are anonymous and Go then delegates automatically .

这将您的示例简化为:

type EvenCounter3 struct {
    INumber
}

func (this *EvenCounter3) IncTwice() {
    this.Inc() // using this.n.Inc() twice makes it slower
    this.Inc()
}

注意 String() 是自动委托(delegate)的(在 Go 语言中是“提升的”)。

至于调用 Inc() 两次使其变慢,好吧,这是使用接口(interface)的限制。接口(interface)的要点是不公开实现,因此您无法访问其内部数字变量。

关于types - 无开销的开关接口(interface)实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14869440/

有关types - 无开销的开关接口(interface)实现的更多相关文章

  1. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  4. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  7. ruby-on-rails - Rails 单表继承 : How to override the value written to the type field - 2

    在我的系统中,我已经定义了STI。Dog继承自Animal,在animals表中有一个type列,其值为"Dog"。现在我想让SpecialDog继承自dog,只是为了在某些特殊情况下稍微修改一下行为。数据还是一样。我需要通过SpecialDog运行的所有查询,以返回数据库中类型为Dog的值。我的问题是因为我有一个type列,rails将WHERE"animals"."type"IN('SpecialDog')附加到我的查询中,所以我不能获取原始的Dog条目。所以我想要的是以某种方式覆盖rails在通过SpecialDog访问数据库时使用的值,使其表现得像Dog。有没有办法覆盖用于类型

  8. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

随机推荐