Oop 是否可以在尾部节点设计一个类型安全的链表来阻止getNext()?
例如,我想知道是否可以设计一个类型安全的单链表结构,这样就不可能从尾部节点请求下一个节点 同时,客户端需要能够通过Oop 是否可以在尾部节点设计一个类型安全的链表来阻止getNext()?,oop,reflection,data-structures,types,type-safety,Oop,Reflection,Data Structures,Types,Type Safety,例如,我想知道是否可以设计一个类型安全的单链表结构,这样就不可能从尾部节点请求下一个节点 同时,客户端需要能够通过node.getChild()遍历(递归或其他方式)列表,但在编译时(至少通过人工编写的显式类型检查)不能越过尾部 我想知道: 这类问题有名字吗 是否有一种面向对象或其他方法可以帮助避免显式的运行时类型检查 实现语言并不重要,但这里有一个Java示例,说明了我的想法 在Joop的回答后编辑: public class TestHiddenInterfaces { interfa
node.getChild()
遍历(递归或其他方式)列表,但在编译时(至少通过人工编写的显式类型检查)不能越过尾部
我想知道:
public class TestHiddenInterfaces {
interface Node { HasNoChildNode getTail(); }
interface HasNoChildNode extends Node {};
interface HasChildNode extends Node { Node getChild(); }
class HasNoChild implements HasNoChildNode {
@Override public HasNoChildNode getTail() { return this; }
}
class HasChild implements HasChildNode {
final Node child;
@Override
public Node getChild() { return child; }
HasChild(Node child) {
this.child = child;
}
@Override public HasNoChildNode getTail() {
if(child instanceof HasChild) return ((HasChild) child).getTail();
else if(child instanceof HasNoChild) return (HasNoChildNode) child;
else throw new RuntimeException("Unknown type");
}
}
@Test
public void test() {
HasNoChild tail = new HasNoChild();
assertEquals(tail, tail.getTail());
HasChild level1 = new HasChild(tail);
assertEquals(tail, level1.getTail());
HasChild level2 = new HasChild(level1);
assertEquals(tail, level2.getTail());
}
}
这种层次结构存在的唯一方式是,如果每个级别实现了不同的接口(在这里,我使用的是比特定语言术语更广义的接口) 根节点无法实现
getParent
——这是实现我能想到的编译错误的唯一方法。因此,根节点的“接口”不包括getParent
第一个子节点可以实现getParent
——但为了编译安全,它们必须在编译时返回一个已知为根节点的类型(即不实现getParent
)
在下一个级别,getParent
的实现必须返回一个类型,该类型实现一个getParent
,该类型返回一个没有getParent
的根节点
简言之,即使您选择生成这样一个实现,它也会非常脆弱,因为您需要编写不同的代码来处理层次结构的每个级别
在运行时检查是正确的情况下会出现某些问题,这就是其中之一。如果每个问题都可以在编译时解决,那么每个编译的程序都只是一组结果(可能是一个巨大的switch语句,用于选择要输出的结果)这种层次结构存在的唯一方式是如果每个级别实现了不同的接口(在这里,我使用的是比特定语言术语更广泛的界面) 根节点无法实现
getParent
——这是我能想到的唯一实现编译错误的方法。因此,根节点的“接口”不包括getParent
第一个子节点可以实现getParent
——但为了编译安全,它们必须在编译时返回一个已知为根节点的类型(即不实现getParent
)
在下一个级别,getParent
的实现必须返回一个类型,该类型实现一个getParent
,该类型返回一个没有getParent
的根节点
简言之,即使您选择生成这样一个实现,它也会非常脆弱,因为您需要编写不同的代码来处理层次结构的每个级别
在某些情况下,运行时检查是正确的,这就是其中之一。如果每个问题都可以在编译时解决,那么每个编译的程序将只是一组结果(可能是一个巨大的switch语句,用于选择要输出的结果)在Scala中,one使用“case-types”在Java或UML图表中,我们经常看到分支和叶之间的区别,这可以减少未使用叶子树的一半内存 这些类型与枚举值一样共存 因此,可以使用以下方法:
/**
* Base of all nodes. For the remaining types I have dropped the type parameter T.
*/
public interface Node<T> {
void setValue(T value);
T getValue();
}
public interface HasParent extends Node {
void setParent(HasChildren node);
HasChildren getParent();
}
public interface HasChildren extends Node {
void setChildren(HasParent... children);
HasPOarent[] getChildren();
}
public final class RootBranch implements HasChildren {
...
}
public final class SubBranch implements HasChildren, HasParent {
...
}
public final class Leaf implements HasParent {
...
}
public final class RootLeaf implements Node {
...
}
我个人认为这在Java中是过分的,但在Scala中,例如类型声明是构造函数,这是有意义的:SubBranche(parent,child1,child2)
在Scala中使用“case-types”在Java或UML图表中,我们经常看到分支和叶之间的区别,这可以减少未使用叶子树的一半内存
这些类型与枚举值一样共存
因此,可以使用以下方法:
/**
* Base of all nodes. For the remaining types I have dropped the type parameter T.
*/
public interface Node<T> {
void setValue(T value);
T getValue();
}
public interface HasParent extends Node {
void setParent(HasChildren node);
HasChildren getParent();
}
public interface HasChildren extends Node {
void setChildren(HasParent... children);
HasPOarent[] getChildren();
}
public final class RootBranch implements HasChildren {
...
}
public final class SubBranch implements HasChildren, HasParent {
...
}
public final class Leaf implements HasParent {
...
}
public final class RootLeaf implements Node {
...
}
我个人认为这在Java中有点过头了,但在Scala中,类型声明是构造函数,这是有意义的:
子分支(parent,child1,child2)
您是否想过让请求父节点检查空父节点(如果未设置,则默认为空)或者在该点抛出一个异常(节点的客户端将对此进行检查),或者具有一些其他智能默认行为,这些行为将记录在javadoc中并由客户端进行检查?我不知道“//不类型安全”是什么意思。在上一个断言中,您说:level2.getParent().getParent()。这将返回根节点。为什么该断言会失败?除非将其强制转换为(非根)类型,否则将无法对根节点调用getParent(),这将导致ClassCastException。因此,是的,识别根节点的唯一方法是使用某种运行时检查。@Jack我打算使用语言支持使方法不存在,如我在接口RootNode extensed Node{};
行中所示。@glenviewjeff,另请参阅它演示了一个与您所问内容类似的数据结构。(它使用一个持久堆栈ADT演示了这个想法,它使用C#递归泛型实现为反向链接列表。)您是否想过让请求父节点的节点检查null父节点(如果未设置,则默认为null)并在该点抛出异常(节点的客户端将检查该异常)或者有一些其他智能默认行为,这些行为会记录在javadoc中并由客户端检查?我不知道你的意思是什么