我试图建立一个数据库模型。
我有三个数据库、模式和表的抽象类。每个数据库应该能够返回所有模式,每个模式应该能够返回所有表。接下来,我为一个数据库创建了示例,其中有两个模式,每个模式都包含to表。
抽象类具有类型参数,以确保不同数据库的模式类型不会混合。所有数据库的模式都应该是模式,但是一个特定数据库的特定模式不应该在另一个数据库中使用,而应该在它自己的数据库中使用。
代码如下:
import java.util.List;
public class main
{
// Abstract
static abstract class Database
{
public abstract List<Schema<? extends Database>> schemas ();
}
static abstract class Schema<D extends Database>
{
public abstract List<Table<D,? extends Schema<D>>> tables ();
}
public abstract class Table<D extends Database,S extends Schema<D>>
{
}
// Concrete
static class Database_1 extends Database
{
@Override
public List<Schema<Database_1>> schemas () {
return List.of (new Database_1_Schema_1(),
new Database_1_Schema_2());
}
}
static class Database_1_Schema_1 extends Schema<Database_1>
{
@Override
public List<Table<Database_1, Database_1_Schema_1>> tables () {
return List.of (new Database_1_Schema_1_Table_1(),
new Database_1_Schema_1_Table_2());
}
}
static class Database_1_Schema_1_Table_1 extends Table<Database_1, Database_1_Schema_1> { }
static class Database_1_Schema_1_Table_2 extends Table<Database_1, Database_1_Schema_1> { }
static class Database_1_Schema_2 extends Schema<Database_1>
{
@Override
public List<Table<Database_1, Database_1_Schema_2>> tables () {
return List.of (new Database_1_Schema_2_Table_1(),
new Database_1_Schema_2_Table_2());
}
}
static class Database_1_Schema_2_Table_1 extends Table<Database_1, Database_1_Schema_2> { }
static class Database_1_Schema_2_Table_2 extends Table<Database_1, Database_1_Schema_2> { }
// Main
public static void main (String ...arguments) throws Exception
{
}
}
代码无法编译。当我试图编译它时,我得到了几个错误。其中大多数是间接错误。我不明白的主要错误如下:
main.java:26: error: schemas() in Database_1 cannot override schemas() in Database
public List<Schema<Database_1>> schemas () {
^
return type List<Schema<Database_1>> is not compatible with List<Schema<? extends Database>>
类型 List<Schema<Database_1>>
与 Database_1
延伸 Database
不兼容: List<Schema<? extends Database>>
.
为什么?这个看起来很像。第一个是第二个的子集。为什么不能用具体类的特定类型来满足抽象类的一般要求?
1条答案
按热度按时间r8xiu3jd1#
让
Cat
是的一个子类型Animal
. 然后我们写猫≺ 动物。让PersianCat
是的一个子类型Cat
因此波斯≺ 猫。关系是可传递的。波斯≺ 猫和猫≺ 动物=>波斯≺ 动物。这种关系是反身的(猫≺ cat),但不是对称的(cat≺ 动物并不意味着动物≺ 猫)。因此,这种关系是一种秩序。
不变性
但是,泛型类型是不变的。
List<Cat>
根本不是List<Animal>
,考虑到以下代码段,这是有充分理由的:让我们假设一下
List<Cat>
≺List<Animal>
重新考虑一下代码片段,稍作改动:因此,泛型是不变的。它们都能保证你能在它们里面投入什么,你能从中得到什么。您可以通过使用co或contarvariant类型边界来简化这些要求。
逆变
List<? super Dog>
是反变的。我们只能把狗放进去,但什么都没说出来。因此,我们得到object,因为它是类型层次结构的根(它是子类型关系中最大的元素,顺序的上确界)。List<? super Dog> dogs = new ArrayList<Animal>();
这很管用,因为我们可以把狗放进去。动物是物体,所以我们可以把物体拿出来。协方差
我们可以使用
extends
. 协变类型可以保证从类型中得到什么。List<? extends Animal>
是协变的。你一定能把动物弄出来。List<? extends Animal> animals = new ArrayList<Cat>();
是允许的,因为猫是动物≺ 动物)和get(int)
给你动物。当然,他们都是猫,但猫是动物,所以这很好。不过,添加内容比较困难,因为您实际上没有可以输入的类型:
return type List<Schema<Database_1>> is not compatible with List<Schema<? extends Database>>
```
Schema<Database_1>
不是的子类型Schema<? extends Database>
.Schema<? extends Database>
必须接受任何类型的t≺ 数据库。然而,Schema<Database_1>
只接受包含t的类型≺ 数据库1。请考虑以下代码段:
最后一行现在应该清楚了。我们不能分配
schemas_N
名单schemas_1
,因为两者都期望不同的类型。他们根本不相容。因此,如果您的方法预期返回
List<Schema<? extends Database>>
(这意味着你可以Schema<Database_2>
你不能退回List<Schema<Database_1>>
,因为它不接受上述类型。重写方法时,不能以不兼容的方式更改它们,因此会出现以下错误: