- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我的项目中每个实体基本上有两种类型,它们只能通过在类泛型声明中指定父目录类型来区分。目录本身是用泛型声明的,因为它们可以链接到相同类型的特定旧目录。
abstract class AbstractCatalog<T extends AbstractCatalog<T>> {
public abstract T getOld();
}
class Catalog1 extends AbstractCatalog<Catalog1> {
@Override
public Catalog1 getOld() { ... }
}
class Catalog2 extends AbstractCatalog<Catalog2> {
@Override
public Catalog2 getOld() { ... }
}
到目前为止一切顺利,但问题是如果我添加一些必须包含指向特定类型目录的链接的实体,它会变得非常麻烦。
例如,
abstract class AbstractCatalogHistory<C extends AbstractCatalog<C>, E extends AbstractHistoryEntry<C, E>> {
public abstract Set<E> getEntries();
}
abstract class AbstractHistoryEntry<C extends AbstractCatalog<C>, E AbstractHistoryEntry<C, E>> {
public abstract E getPrior();
}
class Cat1HistoryEntry extends AbstractHistoryEntry<Catalog1, Cat1HistoryEntry> {
@Override
public Cat1HistoryEntry getPrior() { ... }
}
class Cat2HistoryEntry extends AbstractHistoryEntry<Catalog2, Cat2HistoryEntry> {
@Override
public Cat2HistoryEntry getPrior() { ... }
}
class Catalog1History extends AbstractCatalogHistory<Catalog1, Cat1HistoryEntry> {
@Override
public Set<Cat1HistoryEntry> getEntries() { ... }
}
class Catalog2History extends AbstractCatalogHistory<Catalog2, Cat2HistoryEntry> {
@Override
public Set<Cat2HistoryEntry> getEntries() { ... }
}
因此,在查看这样的层次结构时,很难了解正在发生的事情。这个例子绝不是完整的,我有几十种类型应该嵌套在我上面提供的那些类型中。
我这样做的目的是利用可以在编译时验证的类型安全代码。但与此同时,这样的代码变得非常困惑,因为我必须在向层次结构添加新类型时指定更长的泛型链。
有没有办法处理这种泛型爆炸?
最佳答案
您的示例并没有完全说明为什么您需要为 Catalog1
设置单独的类和 Catalog2
,但我们假设这是已设置的。
但是,即使如此,我也看不出为什么引用这些目录的所有其他内容都需要这种复制。如果您只想确保它与正确的目录类型相关联,那么这是您真正需要的唯一通用参数:
class CatalogHistory<C extends AbstractCatalog<C>> {
public Set<HistoryEntry<C>> getEntries();
}
class HistoryEntry<C extends AbstractCatalog<C>> {
public HistoryEntry<C> getPrior();
}
但是,如果您实际上在做不同的事情,例如Cat1HistoryEntry
和 Cat2HistoryEntry
所以你需要单独的类(class)?在那种情况下,您显然不能绕过抽象基类和两个具体实现,但我认为没有必要引入泛型类型,然后按照您的方式将它们固定为具体类型:
abstract class AbstractHistoryEntry<C extends AbstractCatalog<C>> {
public abstract AbstractHistoryEntry<C> getPrior();
}
class Cat1HistoryEntry extends AbstractHistoryEntry<Catalog1> {
@Override
public Cat1HistoryEntry getPrior() { ... }
}
class Cat2HistoryEntry extends AbstractHistoryEntry<Catalog2> {
@Override
public Cat2HistoryEntry getPrior() { ... }
}
这里发生了一些事情。首先,考虑 AbstractHistoryEntry
.如果你有其中之一,你是在通用级别上工作,不应该关心 getPrior
返回这个或那个具体的子类型——你只需要知道它返回另一个 AbstractHistoryEntry
引用同一目录的对象。
如果你有一个具体的Cat1HistoryEntry
但是引用,您仍然可以获得另一个 Cat1HistoryEntry
的完整类型安全性来自 getPrior
感谢 Java 中返回类型的协方差。
现在它变得稍微复杂一些 - 让我们尝试用 AbstractCatalogHistory
来玩同样的把戏:
abstract class AbstractCatalogHistory<C extends AbstractCatalog<C>> {
public abstract Set<? extends AbstractHistoryEntry<C>> getEntries();
}
class Catalog1History extends AbstractCatalogHistory<Catalog1> {
@Override
public Set<Cat1HistoryEntry> getEntries() { ... }
}
class Catalog2History extends AbstractCatalogHistory<Catalog2> {
@Override
public Set<Cat2HistoryEntry> getEntries() { ... }
}
如您所见,两个具体子类仍然返回一组具体类型 Cat1HistoryEntry
和 Cat2HistoryEntry
.抽象基类型现在需要为这些集合表达一个公共(public)父类(super class)型,以便您可以以通用方式处理结果。这是通过引入协方差来完成的。
二传手
二传手让事情变得有点复杂。基本上,如果你有一个像 List<T>
这样的通用容器/集合或 AbstractCatalogHistory<C>
,并且您希望同时允许添加和检索项目,如果您希望类型安全,则项目类型不能再有差异。
例如,如果您在 AbstractCatalogHistory<C>
中有一个二传手这允许您添加任何 AbstractHistoryEntry<C>
项到历史记录,那么你就有问题了,因为如果你的 AbstractCatalogHistory<C>
实际上是一个 Catalog1History
那么你只想要 Cat1HistoryEntry
里面的元素!
这是与通用列表相同的问题:A List<Cat>
不是 List<Mammal>
因为你可以在 List<Mammal>
中添加一头大象, 但你不应该能够将大象添加到 List<Cat>
.
如果您坚持认为 Catalog1
的历史记录必须仅包含 Cat1HistoryEntry
项,那么一个解决方案是只向 Catalog1History
添加一个 setter , 而没有到 AbstractCatalogHistory<C>
.这样,通用类将仅用于读取历史记录,而不用于编写历史记录。
但是,回到我回答的开头:如果您实际上不需要双重具体类,那么解决方案仍然非常简单。不幸的是,您仍然没有解释为什么或是否需要这些。如果你真正想要的是 Catalog1
/Catalog2
区别,你实际上并不需要不同的实现,例如Cat1HistoryEntry
和 Cat2HistoryEntry
,那么以下内容就足够了:
class CatalogHistory<C extends AbstractCatalog<C>> {
public Set<HistoryEntry<C>> getEntries();
public void addEntry(HistoryEntry<C> entry);
}
class HistoryEntry<C extends AbstractCatalog<C>> {
public HistoryEntry<C> getPrior();
public void setPrior(HistoryEntry<C> prior);
}
关于java - 庞大的 Java 类层次结构中繁琐的泛型声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34150473/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!