我偶然发现了对 java 继承的好奇心,我希望你能就此提出更好的想法:
假设有两个接口(interface)A和A1
接口(interface) A1 扩展 A
接口(interface) A 有一个返回泛型类型的方法。
通用类型类似于 GenericType<T> .
现在的一个基本想法是将这个通用返回类型从
GenericType<Object>在接口(interface)A中
GenericType<String>在A1界面
一开始似乎很容易(坏事会在后面发生)
我们像这样声明接口(interface)A
public interface InterfaceA {
public GenericType<? extends Object> getAGenericType();
}
和接口(interface)A1一样
public interface InterfaceA1 extends InterfaceA
{
@Override
public GenericType<String> getAGenericType();
}
如您所见,我们被迫编写 GenericType<? extends Object>在接口(interface) A 本身中允许使用基于通用的“子类”覆盖它。
(事实上,泛型类型的泛型参数是子类化的,而不是泛型类型本身)
现在假设 GenericType 有自己的方法,如下所示:
public interface GenericType<D>
{
public void doSomethingWith( D something );
}
现在尝试实例化 A1 效果很好。
尝试实例化 A 会很糟糕。要了解为什么要查看这个“使用接口(interface)”类:
public class LookAtTheInstance
{
@SuppressWarnings("null")
public static void method()
{
InterfaceA a = null;
InterfaceA1 a1 = null;
GenericType<String> aGenericType = a1.getAGenericType();
GenericType<? extends Object> aGenericType2 = a.getAGenericType();
Object something = null;
aGenericType2.doSomethingWith( something );
}
}
你问:“现在呢?”
它在最后一行不起作用。事实上,参数“something”甚至不是来自类型“Object”,而是来自类型“?extends Object”。所以你不能传递声明的“对象”类型。你根本不能传递任何东西。
因此,您最终声明了漂亮的接口(interface),但事实证明,这些接口(interface)无法正确实例化。
您是否知道如何为这样的用例建模,其中子类必须覆盖返回类型,而返回类型是泛型?
或者您将如何处理这样的模型案例?
或者我是否只是在通用声明中遗漏了一个简单的点,而我的示例可以通过这种方式实现?
------------ (1) 根据答案进行编辑------------
一个很好的基本思想是让界面A更加抽象!我一开始也有同样的想法,但是……(这个必须要来)
假设这样做:
我们引入了一个新的接口(interface)AGeneric
public interface InterfaceAGeneric<T>{
public GenericType<T> getAGenericType();
}
现在我们必须从这个新接口(interface)扩展 A 和 A1:
public interface InterfaceA extends InterfaceAGeneric<Object>{}
public interface InterfaceA1 extends InterfaceAGeneric<String>{}
虽然它打破了原始继承的路径,但效果很好。
如果我们希望 A1 仍然可以从 A 扩展,我们必须将 A1 更改为
public interface InterfaceA1 extends InterfaceA, InterfaceAGeneric<String>{}
问题又来了。这是行不通的,因为我们用不同的泛型类型间接扩展了相同的接口(interface)。不幸的是,这是不允许的。
你看到问题了吗?
-
并指出另一种情况:
如果你转换 GenericType<? extends Object>至 GenericType<Object>它显然有效。
示例:
public class LookAtTheInstance
{
public static void main( String[] args )
{
InterfaceA a = new InterfaceA()
{
@Override
public GenericType<? extends Object> getAGenericType()
{
return new GenericType<Object>()
{
@Override
public void doSomethingWith( Object something )
{
System.out.println( something );
}
};
}
};
;
@SuppressWarnings("unchecked")
GenericType<Object> aGenericType2 = (GenericType<Object>) a.getAGenericType();
Object something = "test";
aGenericType2.doSomethingWith( something );
}
}
所以在我看来,方法的参数类型的解析
public interface GenericType<D extends Object>
{
public void doSomethingWith( D something );
}
错了。
如果D统一为“?extends Object”为什么参数类型不强制为“Object”?
这不是更有意义吗?
最佳答案
A basic idea is now to change this generic return type from GenericType in Interface A into GenericType in Interface A1
这是不可能的,因为 Java 泛型是不变的。 [1]
正如您所发现的,您不能让接口(interface)声明返回 GenericType<Object> 的方法。并在子接口(interface)中重写方法以返回 GenericType<String> :后者的返回类型不是前者的子类型。并且有充分的理由!
你尝试过
extend indirectly the same interface with different generic types. This is unfortunately not allowed.
这不可能行得通:例如E 的类型应该是什么在 public E set(int index, E element)在一个同时实现了 List<String> 的类中和 List<Object> ?您的子类接口(interface)必须产生类似的混合: getAGenericType 的返回值在子接口(interface)中必须同时实现 GenericType<String>和 GenericType<Object>界面。正如我们所见,这是不可能的。
编译器不知道你要对 GenericType 中的类型参数做什么(虽然理论上可以发现,但事实并非如此)。如果你有一个 GenericType<String> 类型的变量并分配了一个 GenericType<Object>对它,你很可能最终会放一个 Long String 的实例预期,并获得 ClassCastException你不会想到的地方。
在doSomethingWith变量的方法 GenericType<? extends Object> aGenericType2你可以传递一件事:null . null是唯一一个子类型为 ? extends Object 的对象引用. ? extends Object的下界类型是null类型,在Java中无法表达,只能作为null的类型隐式存在引用。
[1] http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29#Java
关于Java - 当返回类型对自己的方法参数类型使用泛型时覆盖扩展接口(interface)的返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5056595/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t