This question already has answers here:
How can a Java class have no no-arg constructor?
(8 answers)
Closed 9 years ago.
In java tutorials,
http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors. This default constructor will call the no-argument constructor of the superclass. In this situation, the compiler will complain if the superclass doesn't have a no-argument constructor so you must verify that it does. If your class has no explicit superclass, then it has an implicit superclass of Object, which does have a no-argument constructor.
Can anyone provide me with an example where is this compile error possible?
class A
{
int a;
A(int a)
{
this.a=a;
}
}
class B extends A
{
B(int a)
{
this.a=a;
}
}
class C
{
public static void main(String args[])
{
B obj=new B(20);
System.out.println("a = "+obj.a);
}
}
Error:Constructor A in class A cannot be applied to given types;
{
^
required: int
found:no arguments
reason: actual and formal argument lists differ in length
class A
{
public A(int n)
{
}
}
class B extends A
{
}
Say you have a Super class
class Super {
// no constructor
// Java compiler will assign a default constructor
// Super () {}
}
and a Child class
class Child extends Super {
public Child() {
//super(); --> this statement will be inserted by default by Java compiler, even though you don't put it in your code
}
}
And If Super is like this
class Super {
Super(int a) {
// Now this is the only constructor Super class has
// Java doesn't insert a default constructor now..
}
}
Child cannot have no argument constructor, because Super doesn't have it anymore
class `Child` {
Child() {
// super();
//this will be error since there is no "no-argument" constructor in Super
}
}
Related
I'm primarily a Java programmer, so this would be one of those "what is this thing from Java equivalent to in C#" questions. So, in Java, you can restrain a Class type argument at compile time to extend a certain super-class, like so:
public <T extends BaseClass> void foo(Class<T> type) {
...
}
and even
public <T extends BaseClass> T foo(Class<T> type) {
...
}
You can even chain multiple interfaces:
public <T extends BaseClass & BaseInterface1 & BaseInterface2> void foo(Class<T> type) {
...
}
How is this done in C#? I know you can use "where T : BaseClass", but this is only applicable when you have an instance T. What about when you only have a Type instance?
EDIT:
For explanation, here is what I would like to do:
ASSEMBLY #1 (base.dll):
abstract class BaseClass {
abstract void Foo();
}
ASSEMBLY #2 (sub1.dll, references base.dll):
class SubClass1 : BaseClass {
void Foo() {
// some code
}
}
ASSEMBLY #3 (sub2.dll, references base.dll):
class SubClass2 : BaseClass {
void Foo() {
// some other code
}
}
ASSEMBLY #4 (main.dll, references base.dll):
class BaseClassUtil {
static void CallFoo(Type<T> type) where T : BaseClass {
T instance = (T)Activator.CreateInstance(type);
instance.Foo();
}
}
public static void Main(String[] args) {
// Here I use 'args' to get a class type,
// possibly loading it dynamically from a DLL
Type<? : BaseClass> type = LoadFromDll(args); // Loaded from DLL
BaseClassUtil.CallFoo(type);
}
So, in this example, I don't care what class the 'type' variable represents, as long as it is derived from BaseClass, so once I create an instance, can call Foo().
The parts that are not vaild C# code (but rather some Java mockup) are the "generic" Type classes: Type<T> and Type<? : BaseClass>.
No, there is no way to enforce at compile time that a Type be assignable to a generic type. If I understand correctly, what you want is:
void Foo<T>(Type type) { ... } //compile time error if an instace typed `type` is not assignable to `T`.
Which means:
void Foo<IFormattable>(typeof(string)); //ok
void Foo<IDisposable>(typeof(string)); //compile time error
Evidently at runtime it is trival, but the language has no support for this at compile time.
From what I understood you are talking about generic type constraint
public void Foo<T>(Type type) where T:BaseClass, BaseInterface1, BaseInterface2
{
//your code
}
Here another article:Constraints on Type Parameters (C# Programming Guide)
When you define a generic class, you can apply restrictions to the
kinds of types that client code can use for type arguments when it
instantiates your class. If client code tries to instantiate your
class by using a type that is not allowed by a constraint, the result
is a compile-time error.
EDIT:
Here your example. Now if you try to call BaseClassUtil.CallFoo<T> with something different from BaseClass and his derived classes you will receive an compile error. Here full example in dotNetFiddle. So the tricky part is the restriction of your class should happen in the Util class
public static void Main(string[] args)
{
//so your LoadFromDll method should return Type. Type doesn't have generic implementation !
Type type = typeof(SubClass1);
BaseClassUtil.CallFoo<BaseClass>(type);
Type type2 = typeof(SubClass2);
//you can write BaseClassUtil.CallFoo<SubClass2>(type2); if you want
BaseClassUtil.CallFoo<BaseClass>(type2);
}
public class BaseClassUtil
{
public static void CallFoo<T>(Type type) where T : BaseClass
{
T instance = (T)Activator.CreateInstance(type);
instance.Foo();
}
}
public class TestClass
{
public int ID { get; set; }
}
public abstract class BaseClass
{
public abstract void Foo();
}
public class SubClass1 : BaseClass
{
public override void Foo()
{
Console.WriteLine("SubClass 1");
}
}
public class SubClass2 : BaseClass
{
public override void Foo()
{
Console.WriteLine("SubClass 2");
}
}
This question already has an answer here:
Is it possible to override a superclass' method with a parameter extending the superclass' method parameter?
(1 answer)
Closed 6 years ago.
I have an abstract class
public abstract class SuperclassA{
public abstract void method(SuperclassB b);
}
And an implementation
public class SubclassA extends SuperclassA{
#override
public void method(SubclassB b){
}
}
where SubclassB extends SuperclassB.
My NetBeans editor complains that I am not overriding method.
What can I do to actually pass a subclass to method?
In order to override a method of the base class, the sub-class's method must have the same signature.
If you want the overridden method to accept only instances of SubclassB, you can test for it :
public class SubclassA extends SuperclassA
{
#Override
public void method(SuperclassB b){
if (!(b instanceof SubclassB)) {
// throw some exception
}
SubclassB sb = (SubclassB) b;
...
}
}
You can call that method as follows :
SuperclassA a = new SubclassA ();
a.method (new SubclassB ());
Think of the method signatures of a class or interface as a contract or a promise of what it and any subclass can do.
SuperclassA promises to do action method for any SuperclassB. In order for SubclassA to be a SuperclassA it must do action method for all SuperclassB. The issue is that it only does action method for some types of SuperclassB.
Here is the same situation with names that are easier to understand.
abstract class Pet {
// Pet methods
}
class Cat extends Pet {
// Cat methods
}
class Dog extends Pet {
// Dog methods
}
abstract class PetShop {
public abstract void groom(Pet pet);
}
The Pet shop class promises that any PetShop can groom any Pet, including dogs.
PetShop shop = new FranksPetShop();
shop.groom(new Dog());
If we define FranksPetShop like so it only defines how to groom Cat's, any other type of Pet (including dogs) is not defined.
class FranksPetShop {
#Override
public abstract void groom(Cat cat) {
// Groom that cat
}
}
To solve this FranksPetShop has to define how to groom a Pet not just a Cat.
class FranksPetShop {
#Override
public abstract void groom(Pet pet) {
// Groom that pet
}
}
Actual, Method Signature is,
public abstract void method(SuperclassB b);// into abstract class
Your overrided Method Signature must be same, Otherwise it's not
override, in fact it will be treated like overloading,
#override
public void method(SuperclassB b){
}
//OverLoad not Override
public void method(SubclassB b){
}
The method in SubclassA takes in a type of SubclassB. The method in SuperclassA is taking in a type of SuperclassB. You are not overriding the parent class method, you are overloading by using a different type.
Depending on what you are trying to accomplish, you could try this
public class SubclassA extends SuperclassA{
#override
public void method(SuperclassB b){
}
}
Which would override the method you want. As long as SubclassB is a child of SuperclassB, then you will still be able to pass SubclassB in.
You can still have an overloaded method that takes in Subclasss if you want.
public class SubclassA extends SuperclassA{
#override
public void method(SuperclassB b){
}
public void method(SubclassB b){
}
}
Take a look at this thread for more info about overloading vs overriding.
Refer to oracle documentation page on override.
An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method.
The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed.
The overriding method has the same name, number and type of parameters, and return type as the method that it override
In your case, you did not use same method signature.
public void method(SubclassB b){
should be changed to
public void method(SuperclassB b){
Now you can use workaround suggested by Eran by using instanceof
I have a generic class Wood:
public class Wood<A>{
public A element;
public Wood(A element)
{
this.elem = elem;
}
}
and an interface Prec:
public interface Prec<A>{
public boolean prec(A a);
}
I want to a new class, which takes all the attributes from Wood and extends it with some new methods. These methods require the objects of type A, to have implemented the interface Prec. Therefore I thought, that this code works:
public class SortedWood<A extends Prec> extends Wood<A>
{
}
But I get the following errors:
SortedWood.java:1: error: constructor Wood<A#2> cannot be applied to given types:
public class SortedWood<A extends Prec> extetends Wood<A>
required: A#1
found: no arguments
reason: actual and formal argument lists differ in length
where A#1,A#2 are type-variables:
A#1 extends Prec declared in class SortedWood
A#2 extends Object declared in class Wood
What's the problem here, and how can I solve it?
From the JLS §8.8.9:
It is a compile-time error if a default constructor is implicitly declared but the superclass does not have an accessible constructor (§6.6) that takes no arguments and has no throws clause.
This means, if your parent class doesn't have a default constructor, but your child class does, then you have a compilation error on your hands.
Let's remove the generics and look at it like this:
public class Parent {
private int age;
public Parent(int age) {
this.age = age;
}
}
public class Child extends Parent {
public Child() {
}
}
The above code won't compile since Parent doesn't have a default or no-arg constructor in it. The child class can't invoke the parent's constructor since it doesn't exist.
If we fix it so that it does reference super...
public class Child extends Parent {
public Child(int age) {
super(age);
}
}
...then the compiler is happy once more.
I am seeing the following kind of code repeatedly in Mapreduce programs. This is just a snippet of code taken out. The entire code is available here
what does the super call in the constructor do? Does it call the constructor of IntPair.class? why is such a call necessary.
public static class KeyComparator extends WritableComparator {
protected KeyComparator() {
super(IntPair.class, true);
}
#Override
public int compare(WritableComparable w1, WritableComparable w2) {
IntPair ip1 = (IntPair) w1;
IntPair ip2 = (IntPair) w2;
int cmp = IntPair.compare(ip1.getFirst(), ip2.getFirst());
if (cmp != 0) {
return cmp;
}
return -IntPair.compare(ip1.getSecond(), ip2.getSecond()); //reverse
}
}
super(), when used in the constructor will call the constructor of the class which is extended. In this case, it will call the WriteableComparator constructor. You can see more details on super in the java documentation here:
Java super link
In particular, see the section titled "Subclass Constructors".
Does it call the constructor of IntPair.class?
No, It's just a argument that is passed in the super class constructor.
why is such a call necessary?
To avoid the call of no arguments constructor of the super class that is by default added by the compiler.
If there are multiple constructors in the super class then you can be specified which constructor of the super class should be called based on arguments.
Sample code: (Look at the output when KeyComparator object is created)
class WritableComparator {
public WritableComparator(){
System.out.println("default constructor is called");
}
public WritableComparator(Class<?> clazz, boolean flag) {
System.out.println("two arguemnts constructor is called");
}
}
class KeyComparator extends WritableComparator {
public KeyComparator() {
//super(); // by default added by the compiler
super(IntPair.class, true);
}
}
IntPair.class notation is used to get object describing this class. Like here:
Class<?> type = Integer.class;
This type variable is not an instance of Integer class, but instance of object describing Integer type.
Some classes requires you to pass them type of objects you want them to work with. Then, they can for example create new instances of those classes, using this type object.
more about Class class
The following code is a testing program. Why i can't use A(int a), in this program?
public class A {
int a;
void meth(int b) {
a+=b;
}
A(int a) {
this.a=a;
}
}
class B extends A {
int a;
void meh2(int b) {
a+=b;
}
}
why can't pass parameter to constructor? What the reasons? Netbeans error message:
constructor A in class tma1.A cannot be applied to given types;
required: int
found: no arguments
reason: actual and formal argument lists differ in length
In the class B, you need constructor. If you mean that you can't call A from B, that's just because you're extending class A, so you need to use super, which refer to the superclass. For example B could be:
class B extends A {
B(int a) {
//You can put additional code here
// This calls the constructor of A
super(a);
//You can put additional code here
}
int a;
void meh2(int b) {
a+=b;
}
}
Otherwise you need to assign something to the variable a in class B, if you're not omitting something in code
Unless a class has a defined constructor, it automatically has a no-arg constructor that merely calls super().
The complaint from your compiler seems to be: "your no-arg constructor [that you can't see] is calling up to a parent no-arg constructor that doesn't exist."
Class A doesn't have a no-arg constructor because there's another one defined (so java doesn't have to create one).