请参阅Golang接口方法中的implementation-type

时间:2016-08-03 17:43:11

标签: go interface

我想为任何坐标类型的东西定义一个接口,它实现一个Distance()方法,可以用来计算相同类型的另一个坐标类型的距离(可能是笛卡儿,也许是按时间顺序,等等)

这是一般的想法:

    type Distancer interface {
        Distance(other interface{}) int
    }

但这并不为Distance()的参数提供类型安全性,它必须是相同的类型。例如,我可能有一个实现Distance()的ParticularTime结构;传递另一个ParticularTime对象作为参数是有道理的,但传递一个ParticularLocation根本没有意义。

我怀疑至少在某些情况下,这可以在编译时捕获,例如这显然是错误的:

    x := ParticularLocation{}
    y := ParticularTime{}
    distance := x.Distance(y)

有没有办法表达这个限制?或者我必须在Distance()的每个实现中进行运行时类型检查?

我是否以错误的方式思考这个问题?

1 个答案:

答案 0 :(得分:3)

这是enter image description here的同态。如果我们假设 distance 表示expression problem,这也是相对容易概括的,这对于广泛的应用是合理的假设。但是,由于Go不支持euclidean distance或任何想要的东西,我们将不得不在我们想要支持的维度数量上做出合理的妥协,转而支持类型安全。

让我们为前三个维度实现这一点。

func OneDimensionalDistance(a OneVectorer, b OneVectorer) float64 {
    return euclideanDistance(a.Vector()[:], b.Vector()[:])
}

func TwoDimensionalDistance(a TwoVectorer, b TwoVectorer) float64 {
    return euclideanDistance(a.Vector()[:], b.Vector()[:])
}

func ThreeDimensionalDistance(a ThreeVectorer, b ThreeVectorer) float64 {
    return euclideanDistance(a.Vector()[:], b.Vector()[:])
}

func euclideanDistance(a, b []float64) float64 {
    // invariant: a and b have same length
    c := 0.0
    for i, _ := range a {
        c += math.Pow(b[i]-a[i], 2)
    }
    return math.Sqrt(c)
}

然后是三种类型安全的方法:

'use strict';

// SystemJS configuration file, see links for more information
// https://github.com/systemjs/systemjs
// https://github.com/systemjs/systemjs/blob/master/docs/config-api.md

/***********************************************************************************************
 * User Configuration.
 **********************************************************************************************/
/** Map relative paths to URLs. */
const map: any = {
  'moment': 'vendor/moment/moment.js',
  'ng2-bootstrap': 'vendor/ng2-bootstrap'
};

/** User packages configuration. */
const packages: any = {
  'moment': {
    format: 'cjs'
  },
  'ng2-bootstrap': {
    format: 'cjs',
    defaultExtension: 'js',
    main: 'ng2-bootstrap.js'
  }
};

////////////////////////////////////////////////////////////////////////////////////////////////
/***********************************************************************************************
 * Everything underneath this line is managed by the CLI.
 **********************************************************************************************/
const barrels: string[] = [
  // Angular specific barrels.
  '@angular/core',
  '@angular/common',
  '@angular/compiler',
  '@angular/forms',
  '@angular/http',
  '@angular/router',
  '@angular/platform-browser',
  '@angular/platform-browser-dynamic',

  // Thirdparty barrels.
  'rxjs',

  // App specific barrels.
  'app',
  'app/shared',
  'app/photos'
  /** @cli-barrel */
];

const cliSystemConfigPackages: any = {};
barrels.forEach((barrelName: string) => {
  cliSystemConfigPackages[barrelName] = { main: 'index' };
});

/** Type declaration for ambient System. */
declare var System: any;

// Apply the CLI SystemJS configuration.
System.config({
  map: {
    '@angular': 'vendor/@angular',
    'rxjs': 'vendor/rxjs',
    'main': 'main.js'
  },
  packages: cliSystemConfigPackages
});

// Apply the user's configuration.
System.config({ map, packages });

所以,一个时间点可以是OneVectorer,笛卡尔点是TwoVectorer,依此类推......

您可以根据自己的需要定义更多类型,以使程序更具表现力,并在其方法中映射到此向量算法。