我有一个抽象类和派生类.看看提供的代码: -
public abstract class Parent{
public Parent(){
init();
}
public abstract void init();
}
public class Child extends Parent{
private String mTitle = null;
public Child(){
super();
System.out.println(mTitle.toString());
}
public void init(){
mTitle = "It' a test";
}
}
Run Code Online (Sandbox Code Playgroud)
当我执行上面的代码时,它将在打印mTitle的值时抛出NullPointerException.如果检查父构造函数中的代码,我调用了抽象方法,它将调用派生类的init方法,在抽象方法中,我将mTitle值的值初始化为="它是一个测试";
在调用父构造函数派生类之后必须调用System.out.println.
如果它以这种方式进行,那么为什么它会抛出NullPointerException.
但是,如果我只是离开mTitle的赋值它不会抛出异常,如: -
private String mTitle;
Run Code Online (Sandbox Code Playgroud)
如果在调用类的构造时发生变量的初始化,并且我们知道默认情况下全局对象已初始化为null.但在这种情况下,它不会抛出异常.
我需要为抽象基础模型编写一些单元测试,它提供了其他应用程序应该使用的一些基本功能.为了测试目的,有必要定义一个继承它的模型; 是否有任何优雅/简单的方法来定义该模型仅用于测试?
我看到一些"黑客"使这成为可能,但从未在django文档或其他类似的地方看到过"官方"方式.
考虑以下代码:
class abstract Normal1 extends Something
{
}
class Outer
{
class abstract Inner extends Normal1
{
}
}
class General extends Outer.Inner // Problem occurs at this
{
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是"由于一些中间构造函数调用,没有可用的PerfHelper类型的封闭实例"
我的问题是我可以像上面那样扩展内部类吗?
我理解为什么我们需要Java中的Abstract Class - 来创建子类.但同样可以通过具体的课程来实现.例如,Child Child扩展Parent.在这里,父母可以很好地抽象和具体.那么为什么我们有抽象?
根据PHP手册,这样的类:
abstract class Example {}
Run Code Online (Sandbox Code Playgroud)
无法实例化.如果我需要一个没有实例的类,例如注册表模式:
class Registry {}
// and later:
echo Registry::$someValue;
Run Code Online (Sandbox Code Playgroud)
简单地将类声明为抽象是否会被认为是好的风格?如果没有,与抽象类相比,隐藏构造函数作为受保护方法有什么好处?
问的理由:据我所知,它可能会有一些功能滥用,因为手册将抽象类更多地描述为具有实例化可能性的后续类的蓝图.
更新:首先,感谢所有的答案!但是很多答案听起来很相似:'你不能实例化一个抽象类,但对于注册表,为什么不使用单例模式?'
不幸的是,这或多或少完全是我的问题的重复.使用单例模式(也就是隐藏)与仅仅声明它而不必担心它相比有什么优势?(例如,开发人员之间的强烈内涵,实际上并没有使用类.)__construct()abstractabstract
首先,我阅读了erickson对"为什么我不能在Java接口中定义静态方法?"的有用回复..这个问题不是关于"为什么"而是关于"当时如何?".
虽然我现在确信在大多数情况下我想做的事情是矫枉过正,但有一种情况可能需要:
我再举一个ParametricFunction例子.现在让我们来看一个复杂的函数,比如Bessel函数,其中查找表是合适的.这必须初始化,因此两个选项是将参数直接传递给构造函数或提供init(double[] parameters).后者的缺点是getValue(double x)必须检查每次调用的初始化(或者ArrayIndexOutOfBoundsException必须考虑初始化检查),因此对于时间要求严格的应用程序,我更喜欢构造函数方法:
interface ParametricFunction {
public double getValue(double x);
}
class BesselFunction implements ParametricFunction {
public BesselFunction(double[] parameters) { ... }
public double getValue(double x) { ... }
}
Run Code Online (Sandbox Code Playgroud)
这涉及另一个问题,接口中构造函数的不可能性.那里有什么好的解决方案?我当然可以使用这种init(double[] parameters)方法,但我之所以提到我的原因.
(编辑:好的,这里实现接口的抽象类会这样做)
现在让我们假设ParametricFunction只允许某些参数,例如正整数.如何检查传递给构造函数的参数的真实性?抛出一个IllegalArgument例外是可能的,但checkParametersValidity(double[] parameters)似乎更方便.但是在构造之前需要检查参数,因此它必须是静态方法.这就是我真正想知道的方法,以确保实现ParametricFunction接口的每个类都定义了这个静态方法.
我知道这个例子是相当人为的,不仅仅是init通过接口使用方法的原因值得商榷,我仍然想知道答案.如果您不喜欢它,请将其视为学术问题.
(原例)
所以基本上我希望一个接口提供常用方法和例如getSimilarObject方法.对于(一个组成的)例子
public interface ParametricFunction {
/** @return f(x) using the parameters */ …Run Code Online (Sandbox Code Playgroud) 我决定开始自己做小编码项目,专注于代码质量而不是代码数量,并对抽象类的使用有疑问.
现在我知道抽象类和接口之间的区别与最大的接口(我认为)是接口允许您只定义需要使用接口和类的类实现的方法,允许您同时定义方法和成员如果您愿意,可以使用默认方法.我的问题是使用抽象类与普通类的主要好处是什么?我能想到的两者之间唯一真正的区别是你不能创建一个抽象类的实例.这两者之间还有其他差异吗?
我有一个抽象的基类
class IThingy
{
virtual void method1() = 0;
virtual void method2() = 0;
};
Run Code Online (Sandbox Code Playgroud)
我想说 - "所有提供具体实例化的类都必须提供这些静态方法"
我很想做
class IThingy
{
virtual void method1() = 0;
virtual void method2() = 0;
static virtual IThingy Factory() = 0;
};
Run Code Online (Sandbox Code Playgroud)
我知道没有编译,无论如何它还不清楚如何使用它,即使它编译.无论如何我只能这样做
Concrete::Factory(); // concrete is implementation of ITHingy
Run Code Online (Sandbox Code Playgroud)
根本没有在基类中提到工厂.
但我觉得应该有一些表达我希望实现注册的合同的方式.
这有一个众所周知的习语吗?或者我只是把它放在评论中?也许我不应该试图强迫这个
编辑:当我输入问题时,我觉得自己模糊不清.我觉得应该有一些方法来表达它.伊戈尔给出了一个优雅的答案,但实际上它表明它确实无济于事.我最终还是要做
IThingy *p;
if(..)
p = new Cl1();
else if(..)
p = new Cl2();
else if(..)
p = new Cl3();
etc.
Run Code Online (Sandbox Code Playgroud)
我想像c#,python或java这样的反射语言可以提供更好的解决方案
在抽象类中,哪个访问修饰符必须用于方法,因此子类可以决定它是否应该是公共的?是否可以"覆盖"Java中的修饰符?
public abstract class A {
??? void method();
}
public class B extends A {
@Override
public void method(){
// TODO
}
}
public class C extends B {
@Override
private void method(){
// TODO
}
}
Run Code Online (Sandbox Code Playgroud)
我知道静态绑定会有问题,如果有人打电话:
// Will work
A foo = new B()
foo.method();
// Compiler ?
A foo = new C();
foo.method();
Run Code Online (Sandbox Code Playgroud)
但也许还有另一种方式.我怎么能做到这一点?
我想要做的就是确保类Item的子类实现静态方法,并且我希望在编译时检查它以避免运行时错误.
使用静态方法的抽象类似乎不起作用:
错误:无法将静态成员标记为覆盖,虚拟或抽象
public abstract class Item
{
public static abstract Item GetHistoricalItem(int id, DateTime pastDateTime);
}
public class Customer : Item
{
public static override Customer GetHistoricalItem(int id, DateTime pastDateTime)
{
return new Customer();
}
}
public class Address : Item
{
public static override Address GetHistoricalItem(int id, DateTime pastDateTime)
{
return new Address();
}
}
Run Code Online (Sandbox Code Playgroud)
和接口似乎也不起作用:
错误:客户未实现接口成员GetHistoricalItem()
public class Customer : Item, HistoricalItem
{
public static Customer GetHistoricalItem(int id, DateTime pastDateTime)
{ …Run Code Online (Sandbox Code Playgroud)