- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这两个声明之间是否存在语义差异,还是只是语法糖?
class C<T extends C>
对比class C<T extends C<T>>
背景:我最近回答了一个 question关于使用 C<T extends C>
的泛型方法和同行基于 C<T extends C<T>>
提供了类似的答案.最后,两种选择都提供了相同的结果(在所问问题的上下文中)。我仍然对这两种构造之间的区别感到好奇。
是否存在语义差异?如果是这样,每种方法的含义和后果是什么?
最佳答案
当然 - 通常这些“ self 类型”用于约束子类型以完全返回它们自己的类型。考虑以下内容:
public interface Operation {
// This bit isn't very relevant
int operate(int a, int b);
}
public abstract class AbstractOperation<T extends AbstractOperation<T>> {
// Lets assume we might need to copy operations for some reason
public T copy() {
// Some clever logic that you don't want to copy and paste everywhere
}
}
很酷——我们有一个父类,它有一个有用的运算符,可以特定于子类。例如,如果我们创建一个 AddOperation
,它的通用参数可以是什么?由于“递归”通用定义,这只能是 AddOperation 给我们:
public class AddOperation extends AbstractOperation<AddOperation> {
// Methods etc.
}
因此 copy()
方法保证返回 AddOperation
.现在让我们假设我们是愚蠢的、恶意的、有创意的或其他任何东西,并尝试定义这个类:
public class SubtractOperation extends AbstractOperation<AddOperation> {
// Methods etc.
// Because of the generic parameters, copy() will return an AddOperation
}
这将被编译器拒绝,因为泛型类型不在其范围内。这非常重要——这意味着在父类中,即使我们不知 Prop 体类型是什么(甚至可能是编译时不存在的类),copy()
方法将返回同一子类的实例。
如果您只是选择 C<T extends C>
,然后这个奇怪的定义 SubtractOperation
会是合法的,你失去了关于什么的保证 T
在这种情况下 - 因此减法运算可以将自身复制到加法运算中。
这与其说是为了保护您的类层次结构免受恶意子类的侵害,不如说是它为编译器提供了有关所涉及类型的更强有力的保证。如果你调用 copy
来自另一个类(class)的任意 Operation
,您的一个构造保证结果将属于同一类,而另一个将需要转换(并且可能不是正确的转换,如上面的 SubtractOperation)。
例如:
// This prelude is just to show that you don't even need to know the specific
// subclass for the type-safety argument to be relevant
Set<? extends AbstractOperation> operations = ...;
for (AbstractOperation<?> op : operations) {
duplicate(op);
}
private <T extends AbstractOperation<T>> Collection<T> duplicate(T operation) {
T opCopy = operation.copy();
Collection<T> coll = new HashSet<T>();
coll.add(operation);
coll.add(opCopy);
// Yeah OK, it's ignored after this, but the point was about type-safety! :)
return coll;
}
duplicate
第一行的赋值至 T
对于您提出的两个界限中较弱的一个,不会是类型安全的,因此代码无法编译。 即使您明智地定义了所有子类。
关于java - 泛型:T extends MyClass 与 T extends MyClass<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6523108/
在学习 C++ 的过程中,我偶然发现了文章 Writing Copy Constructors and Assignment Operators它提出了一种机制来避免复制构造函数和赋值运算符之间的代码
显然,以这种方式实现基于类的实例方法是 JavaScript 中的一个习惯用法: function MyClass(){...} MyClass.prototype.methodA = functio
我尝试使用泛型为 NSManagedObject 的子类提供通用方法,但当 Swift 似乎无法找到/将泛型转换为具体类时,我收到错误: /// NSManagedObject+Helper.swif
有什么区别 MyClass mc = MyClass(); 和 MyClass mc; 在 C++ 中? 最佳答案 第一个调用复制构造函数,以临时对象作为参数 - MyClass() 创建临时对象。
考虑不涉及复制省略的情况(C++17 之前)。 来自 cppreference(再次假设 C++14): Temporary objects are created in the following
这里有一些代码: class MyClass { public: int y; }; int main() { MyClass item1; MyClass item2 = M
这种类型转换表达式之间有什么区别?什么是更好的? // One way var t:MyClass = MyClass(o); // Another var t:MyClass = o as MyCl
为了跟踪实例,我们有一个数组 MyClass[] mc = new MyClass[5]; 我想在构造函数调用本身期间保存在此数组中创建的 MyClass 实例。 类似这样的事情: public cl
我在对一个非常简单的类进行子类化时遇到问题,该类也有返回初始类的方法。 public class MyClass { public MyClass(){ } public MyC
我有一个 std::list在我的课上我有 myclass::operator bool PComp(const T * const & a, const T * const & b) { re
我正在编写一个简单的程序来计算面积,我得到的错误是: no matching function for call to 'myclass::myclass()' 我无法理解此错误的原因以及解决方法。
我希望我可以针对这个问题逐字发布我的项目,但我不能。 基本上,我有以下类(class): class Lowest { someValue: string constructo
为什么可以施放MyClass反对 List没有编译错误(只是有“未检查”警告),尽管 MyClass未实现 List 接口(interface),同时无法进行强制转换,例如 String类同样的方式。
我正在这里试验一下。 假设我有一个类: static class MyClass { static String property = "myProperty"; } 和一个方法: publi
我正在尝试为单元测试目的创建一个 stub 类。 Stub 指向完全相同的 EmployeeData 类定义,但编译器认为它们是不同的,不知何故。结果,我不断收到以下消息: Cannot implic
为什么我不能通过 Point src[1][4] = { { Point(border,border), Point(border,h-border),
我有一个正在创建的模板类,我需要一个方法来返回该类的对象并对其进行分配。我有一个方法接收 2 个对象、创建一个新对象并返回它,以及重载赋值运算符以正确复制成员。 我试过用两种方法来做到这一点(两种方法
在 C# 中是否可以在运行时创建一个类型,该类型继承自泛型类,其中基类的模板参数是正在构造的当前类?这将编译正常: // I have this class: public class OtherCl
我有几个带有“listingThumb”类的 div CSS: .listingThumb{ height:50px; width:50px; overflow:hidden; } HTML: 我希
例如,我有一个包含不同容器的类来保存由 new 运算符创建的 MyClass 对象: class A{ MyClass* m; vector vm; vector > vvm;
我是一名优秀的程序员,十分优秀!