gpt4 book ai didi

Java 接口(interface)和模板困惑

转载 作者:行者123 更新时间:2023-11-30 08:26:54 25 4
gpt4 key购买 nike

我正在阅读一些关于一些不同编程语言的模板之间差异的问题。我明白这主要归功于这个问题:What are the differences between Generics in C# and Java... and Templates in C++? .然而,当他开始谈论接口(interface)和添加一些东西时,我确实对接受的答案的结尾有点困惑。我主要从这个问题中了解接口(interface)的将军:Explaining Interfaces to Students .我仍然对问题中所说的内容感到困惑。那么有人可以更好地解释最后一部分:

Because of this, the C++ compiler places no restrictions on what you can do with templates - basically any code you could write manually, you can get templates to write for you. The most obvious example is adding things:

In C# and Java, the generics system needs to know what methods are available for a class, and it needs to pass this down to the virtual machine. The only way to tell it this is by either hard-coding the actual class in, or using interfaces. For example:

string addNames( T first, T second ) { return first.Name() + second.Name(); }

That code won't compile in C# or Java, because it doesn't know that the type T actually provides a method called Name(). You have to tell it - in C# like this:

interface IHasName{ string Name(); }; string addNames( T first, T second ) where T : IHasName { .... }

And then you have to make sure the things you pass to addNames implement the IHasName interface and so on. The java syntax is different (), but it suffers from the same problems.

The 'classic' case for this problem is trying to write a function which does this

string addNames( T first, T second ) { return first + second; }

You can't actually write this code because there are no ways to declare an interface with the + method in it. You fail.

C++ suffers from none of these problems. The compiler doesn't care about passing types down to any VM's - if both your objects have a .Name() function, it will compile. If they don't, it won't. Simple.

我真的很想了解这个答案中的代码,因为我很困惑 .Name() 方法在 IHasName 接口(interface)中的工作方式。有人有更好的例子可以进一步解释如何使用接口(interface)将名称之类的东西添加到 Person 类或其他东西......

编辑:我对 Java 代码更感兴趣。

最佳答案

“+”在 C++ 中编译的原因是 C++ 模板(C++ 专家请原谅我的笨拙)就像巨大的宏。它将等到模板被实例化以检查每个操作是否可行(仍在编译时,正如 foo 在他们的评论中警告我的那样)。

例如这段代码:

#include "stdafx.h"

#include <stdio.h>

#include <vector>
#include <iostream>

template <class T> class adder {
public:
adder();
T add(T t1, T t2);
};


template <class T> adder<T>::adder() {}

template <class T> T adder<T>::add (T t1, T t2) {
return t1 + t2;
}

using namespace std;

typedef vector<int> int_vector;


int _tmain(int argc, _TCHAR* argv[])
{

adder<int_vector> vector_adder;
int_vector v1;
int_vector v2;

v1.push_back(1);
v1.push_back(2);

v2.push_back(3);
v2.push_back(4);
v2.push_back(5);

// will fail here, in compile time!
int_vector v3 = vector_adder.add(v1, v2);

for (int_vector::iterator it = v3.begin(); it != v3.end(); it++) {
cout << *it;
}

return 0;
}

在我尝试添加两个 vector 之前将完美运行;在那一刻,C++ 编译器将意识到我在模板中使用的实际类型没有重载。但是,我可以在模板中定义一些其他操作,如果我没有尝试添加实际类型,编译器将不会意识到(然后它会尝试解决宏)。但是像 adder<int> 这样的东西将完美地工作。

Java 不允许您达到这一点,因为它不允许对泛型类型进行实际操作(定义泛型包含非常好,例如 java.util.* 下的类,但仅此而已)。最好的办法是像 java 文档中那样选择有界类型泛型:

public class NaturalNumber<T extends Integer> {

private T n;

public NaturalNumber(T n) { this.n = n; }

public boolean isEven() {
return n.intValue() % 2 == 0;
}

// ...
}

在这里您可以将泛型的类型限制为某个父类(super class),并对其进行一些操作。

关于Java 接口(interface)和模板困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21171688/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com