Making methods only accessible to child classes, not instantiated objects - java

public class Flight{
private int flying = 0;
public boolean fly() {
flying = 1;
return isFlying();
}
private isFlying(){
return flying > 0;
}
}
public class CargoFlight extends Flight{
public boolean startFlight(int passengers)
if (passengers <= 0){
return false;
}
return fly(); // Want to be able to do this
}
}
public class Airport{
public static void main(){
CargoFlight f1 = new CargoFlight();
f1.fly(); // Don't want to be able to do this
}
}
f1 has the property fly(), is there any way to restrict it such that the method fly() can be called inside the body of the classes extending Flight (like CargoFlight here), but cannot be called using the instances of the subclasses (like f1)? I have added comments to the code to make it clear.

The nearest access specifier to what you want is protected. However, protected members are still always accessible to other classes in the same package, so it won't prevent access from your Airport class.
If you really need the subclass to block access to the method except to the subclass, then you can override it in the subclass to always throw an exception, then use super to invoke the original method:
public class Flight {
private int flying = 0;
protected boolean fly() {
flying = 1;
return isFlying();
}
private boolean isFlying() {
return flying > 0;
}
}
public class CargoFlight extends Flight {
#Override
protected boolean fly() {
throw new IllegalAccessError();
}
public boolean startFlight(int passengers) {
if (passengers <= 0) {
throw new IllegalArgumentException();
}
return super.fly();
}
}
The flaw with any solution though, is that it violates the Liskov substitution principle. A CargoFlight is no longer a proper instance of Flight because it doesn't have the normal fly method that other Flights have. If you intend fly only to be called by subclasses and never directly, then it's okay (although you should document that rule in the method Javadoc), but it still leaves you without the nicety of having a polymorphic method to call to tell generic Flights to fly.
A nicer solution, if it can fit with your design, would be to have fly and startFlight be the same method (that means same name and same arguments, and the same return type or a subtype), so then the subclass method could simply override the base implementation. The only method outside callers would see is fly. That means that your passengers argument either needs to be part of the base method Flight.fly too, or, remove it from both method implementations and make it into a separate property setPassengers for those subclasses that need it:
public class CargoFlight extends Flight {
private int passengers = 0;
public void setPassengers(int p) {
passengers = p;
}
#Override
public boolean fly() {
if (passengers <= 0) {
throw new IllegalStateException(); // or whichever
}
return super.fly();
}
}

Related

How do I check which subclass was passed into a constructor?

I am relatively new to Java and programming, so I apologize if this question seems stupid. I am creating a battle-game for a Java programming class -- I have a Hero class with some basic methods and a subclass Paladin that extends Hero but with its own unique methods added in. I want to have a Battleground object that passes in ANY Hero class but then check which specific subclass was passed in. How do I determine which of the Hero subclasses were passed in?
public class Hero {
private String name;
private int hitPoints;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
}
public String getName() { return this.name; }
public int getHitPoints() { return this.hitPoints; }
public void takeDamage(int amount) { this.hitPoints -= amount; }
}
And here is the Paladin Class
public class Paladin extends Hero {
public Hero (String name, int hitPoints) {
super(name, hitPoints);
}
public void heal(int amount) {
this.hitPoints += amount;
}
}
So in the battleground class, I have a method that attempts (incorrectly) to check if the hero passed in is a Paladin. How would I go about doing this? The if statement is a placeholder psuedo-code just to clarify what I mean.
public class Battleground {
private Hero player;
public Battleground (Hero player) {
this.player = player;
}
public void startRound() {
// HERE!!
if (player.equals(Paladin)) {
player.heal();
}
}
}
Thinking in terms of what your classes are actually modelling, it doesn't make much sense for a battleground to know that a Paladin heals themselves at the start of a round, nor for the battleground to be responsible for making sure the Paladin heals themselves.
A more sensible design would be for the game to inform the hero that the round has started, and let the particular Hero subclass control what that kind of hero does when the round starts. For example:
public class Hero {
// ...
public void onRoundStart() {
// do nothing
}
}
public class Paladin extends Hero {
// ...
#Override
public void onRoundStart() {
// your heal method takes an int as its argument
heal(10);
}
}
public class Battleground {
// ...
public void startRound() {
// let the particular Hero subclass control what happens
player.onRoundStart();
// ...
}
}
This way you don't need any if statements or instanceof checks, but also the code defining a Paladin's behaviour is in the Paladin class where it sensibly belongs. If you want to change the rules for Paladins later, it will be easier to know which class you need to edit.
This kind of refactoring is called "replace conditional with polymorphism".
Using Instanceof is Considered a Code Smell Sometimes
Using instanceof can be considered to be a code smell - which means a bad practice.
There is an alternative for you to consider.
Add the heal() method to the Hero class, but leave the implementation blank.
Put only an implementation in the Paladin class. Then, even though heal() will be called on all players, it will only do something inside Paladins.
However... if you still need to detect the class type...
Ways to Detect the class
There are multiple ways to differentiate between classes.
Instance of is one.
Another is having different constructors.
A third is having an ENUM or String field called EntityType.
In your case, I think instanceof or using a special field make the most sense.
Instanceof
if(player instanceof Paladin)
Using a Special Field
Quick Example Hero
public class Hero {
private String name;
private int hitPoints;
private int HeroType;
public Hero (String name, int hitPoints) {
this.name = name;
this.hitPoints = hitPoints;
this.heroType = BASIC_HERO;
}
public static int BASIC_HERO = 0;
public static int PALADIN_HERO = 1;
...
}
Quick Example Paladin
public class Paladin extends Hero {
public Paladin(String name, int hitPoints) {
super(name, hitPoints);
this.heroType = PALADIN_HERO;
}
}
Detecting the Type
You would have a method in both classes called getHeroType().
if(hero.getHeroType == Hero.PALADIN_HERO){
}else if(hero.getHeroType == Hero.BASIC_HERO){
}
If you want, you can use to check the class of the object:
if (player instanceof Paladin)
No question, this will work. If you don't have a lot of "special" behaviour and a limited small amount of cases, that can be a reasonable solution. But assuming that your game will end up with a lot of special handling for each subclass of Hero and probably not only in the startRound() method of your Battlefield class, your code will someday be cluttered with these instanceof checks. Same applies, if you use a specific type field within the Hero class.
In that case a better solution might be to relocate the logic into special classes and try to avoid type checks if possible or at least have a well defined place for them, if necessary.
Update: removed faulty demo implementation
You can always do player.getClass to get actuall class. As for if statements you can use instanceof operator.
So
if (player instanceof Paladin) {
((Paladin)player).heal();
}

Java Returning Type of Child class (abstract)

I've been trying my best with some basic code, and I am completely stuck...
I have an abstract class "Piece":
public abstract class Piece {
private static int type;
public int getType() {
return type;
}
}
The "Pawn" is the Child:
public class Pawn extends Piece {
private static final int type = 1;
}
And now for the problem: When creating the Pawn with Pawn p = new Pawn();, p.getType() returns 0, not 1...
How can I fix this?
The problem is that you already have a variable declared in your abstract class. You shouldn't redeclare it in your subclass. Instead, set the abstract class's variable like this:
public class Pawn extends Piece {
public Pawn() {
type = 1;
}
}
You should also declare the variable as protected so that subclasses can access it and refrain from making it static, since that will allow only one value for all subclasses:
public abstract class Piece {
protected int type;
public int getType() {
return type;
}
}
This code you write relies on an instance and not on a static context:
Pawn p = new Pawn();
p.getType();
A static final field is not designed to be inherited by child classes.
And creating a static final field in the child class with the same name as in the parent class doesn't allow to override it either.
1) So you should use an instance field and not a static field for the type field.
2) If you want to override the behavior of getType() in the child class, in fact you don't even need to use a field. Using a method should be enough.
In the base class :
public abstract class Piece {
public int getType() {
return 0;
}
}
In the child class :
public class Pawn extends Piece {
#Override
public int getType() {
return 1;
}
}
Here is one way. But you really need to read up on classes and abstract classes.
public abstract class Piece {
public int getType() {
return 0;
}
}
public class Pawn extends Piece {
public int getType() {
return 1;
}
}
Having a static variable in a class means that all instances of that class share the same value. I don't think that's what you intended.
Also, you can use the hierarchy of inheritance to your advantage by not redefining the getType() method.
Here is one of many ways to solve it:
public abstract class Piece {
protected int type;
public int getType() {
return type;
}
}
public class Pawn extends Piece {
public Pawn() {
type = 1;
}
}
There are two problems with your approach.
The first is that Java does not support inheritance of static methods. Not that it couldn't have supported this - it's just a design choice. What this means is that any method of class Piece, which calls getType() - calls the Piece class' implementation of getType(), not a polymorphic call to getType() of whatever the actual subclass is.
The second problem is that you're sort of reinventing the wheel. Java has rich reflection facilities: You can use getClass() and instanceof for your check:
if(myObject instanceof Piece && myObject.getClass() != Piece.class) {
// do stuff
}
and of course you can make this a method of the piece class (no need to override it).

What kind of relationship does an interface have with it implementing class?

A subclass has a relationship that is described as IS-A with it base class, but a base class does not share this kind of relationship with it subclass. I was wandering what kind of relationship an interface have with it implementing class since an object of that class can be passed to interface object and the interface object can only access methods defined it concrete Interface.
public class main {
public static void main(String[]args){
Nigeria ng = new Nigeria(){};
//Interface object can accept Nigerias object which is not posible in Inheritance
Continent continent = ng;
//prints Country is in Africa
continent.Africa();
//continent.language(); will not compile language is not in the interface
//Print Democratic thought this should print Undefined since it is inialied with default.
continent.Goverment();
}
}
interface Continent{
public void Africa();
default void Goverment(){
System.out.println("Undefined");
}
}
class Nigeria implements Continent{
#Override
public void Africa(){
System.out.println("Country is in Africa");
}
public void language(){
System.out.println("Official Language is English");
}
public void Goverment(){
System.out.println("Democratic");
}
}
If you are looking for English-language analogues, an Interface is not an "Is a..." nor "Has a..." relationship, but more an "Is...".
An Interface is not about the class that uses it.
It's about the consumer that asks for it.
If you wanted to see it as anything, you could see it as an adjective.
"He is Responsible".
Well, what does he do?
He finishes tasks; he takes ownership of his mistakes; he makes them right.
Is he a pilot, is he a surgeon, is he a doctor?
Is he a child, a father, a greatGrandfather?
Do you care?
I need a responsible person, to help me do this job.
Does ResponsiblePerson inherit from PoliceOfficer? Does Lawyer inherit from ResponsiblePerson, because I'm sure there can be irresponsible lawyers.
class Lawyer extends Person { }
class ResponsibleLawyer extends Lawyer implements ResponsibleEntity { }
class NeedyPerson extends Person {
public void acceptHelp (ResponsibleEntity somebody) {
try {
somebody.attemptTask( someTask );
} catch (TaskCompletionError err) {
somebody.takeOwnership(err);
somebody.fixMistake(err);
}
}
}
Can corporations be Responsible too?
Perhaps we don't see it too often, but it's theoretically possible:
class LawFirm extends CorporateEntity { }
class BetterLawFirm extends LawFirm implements ResponsibleEntity { }
Can somebody be a responsible corporate body? Well, so long as that corporate body does all of the same things that the responsible person would otherwise do, sure.
In another example, you might have a Switchable interface.
Looking at that name, you could surmise that the thing you're being given has a switch which can be poked.
So what methods might it have?
on( )
off( )
toggle( )
isOn( )
sounds like a useful set to have.
What benefit is there to having an interface like this?
Well, now I know that I can deal with a switch, and its lineage doesn't matter.
If all I want is a class which takes a switch and does something with it, why do I need to create dozens of classes, just to accept my dozens of things with switches?
Or override methods into the dirt to do the same.
class SwitchThrower {
public void throwSwitch (CoffeeMaker coffeeMaker) { coffeeMaker.on(); }
public void throwSwitch (LightSwitch lightSwitch) { lightSwitch.on(); }
public void throwSwitch (GhostTrap ghostTrap) { ghostTrap.on(); }
public void throwSwitch (TheHeat theHeat) { theHeat.on(); }
public void throwSwitch (CarIgnition ignition) { ignition.on(); }
}
...
why not just:
class SwitchThrower {
public void throwSwitch (Switchable switch) { switch.on(); }
}
class LightSwitch implements Switchable {
private boolean currentlyOn;
public LightSwitch (boolean initiallyOn) {
currentlyOn = initiallyOn;
}
public LightSwitch () {
currentlyOn = false;
}
public boolean on () {
currentlyOn = true;
return currentlyOn;
}
public boolean off () {
currentlyOn = false;
return currentlyOn;
}
public boolean toggle (boolean forceOn) {
boolean state;
if (forceOn == true) {
state = on();
} else {
state = off();
}
return state;
}
public boolean toggle () {
boolean state;
if (isOn() == true) {
state = off();
} else {
state = on();
}
return state;
}
public boolean isOn () {
return currentlyOn;
}
}
...et cetera
As you can see, aside from describing a basic feature-set of the implementer, interfaces are not about the class at all, but rather the consumer.
An even more awesome implementation of this, in different languages, is _Traits_.
Traits are typically like Interfaces, but they have default behaviour associated with them.
Looking at my Switchable and my LightSwitch, you could imagine that practically all classes with this switch would have the same methods, with the same method behaviour...
...so why would I rewrite all of those methods over again, if I'm already going through the trouble of defining the signature in the interface?
Why couldn't I just add default behaviour in there, and have it apply to the implementer, unless a method is overridden?
Well, that's what Traits / Mix-Ins allow.
The relationship is only the "contract" that the class is getting to implement the methods the interface is offering.
That is how java can separate WHAT objects can do (Interface) and HOW the inherited class will do it.

Generics in Java preventing calling of methods

So I have custom class that looks like this:
public class Cell {
protected boolean wasActive;
public Cell() {
this.wasActive = false;
}
public boolean getPreviousActiveState() {
return this.wasActive;
}
public void setPreviousActiveState(boolean previousActiveState) {
this.wasActive = previousActiveState;
}
}
Now I am writing another class here I need to call the above getPreviousActiveState() method:
public class Synapse<Cell> {
private Cell cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
this.cell.getPreviousActiveState; // <= CAN'T BE CALLED. WHY?
}
}
I know the problem has to do with the fact that I declared the class:
public class Synapse<Cell>
but I did this so that only a Synapse can only contain a subclass of Cell. For example I also have implemented a VisionCell, AudioCell, and Neuron class that all extend Cell. Was this use of generics unneccesary? If so, when should I use generics? Thanks!
Defining a type parameter called Cell means is creating some confusion. Let's rename it to T, and also add the pair of missing parenthesis to the this.cell.getPreviousActiveState call:
class Synapse<T> {
private T cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
return this.cell.getPreviousActiveState(); // <= CAN'T BE CALLED. WHY?
}
}
The error that you now get is:
The method getPreviousActiveState() is undefined for the type T
Which is the compiler's way of telling you that no where in the code it guaranteed that type parameter T has a getPreviousActiveState() method. Note that Java generic are not like C++ templates: the generic class is compiled once independently of any calling site. In other words: the compiler does not check this class w.r.t to any particular instantiation, but rather it checks that it makes sense on its own.
In order to guarantee that T has a getPreviousActiveState() all you need to do is to specify an upper bound on T that defines this method. We can use Cell itself:
class Synapse<T extends Cell> {
private T cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
return this.cell.getPreviousActiveState(); // <= Compiles!
}
}
Of course, you can make the code more versatile by introducing an interface defining the method(s) you're interested in and using this interface as the upper bound. You will also have to make Cell implement this interface:
interface ActiveStateProvider {
public boolean getPreviousActiveState();
}
class Cell implements ActiveStateProvider {
protected boolean wasActive;
public Cell() {
this.wasActive = false;
}
public boolean getPreviousActiveState() {
return this.wasActive;
}
public void setPreviousActiveState(boolean previousActiveState) {
this.wasActive = previousActiveState;
}
}
class Synapse<T extends ActiveStateProvider> {
private T cell;
// some other methods... like isConnected
public boolean getPreviousActiveState() {
return this.cell.getPreviousActiveState(); // <= Compiles!
}
}

Java overloading vs overriding

Hi I just want to make sure I have these concepts right. Overloading in java means that you can have a constructor or a method with different number of arguments or different data types. i.e
public void setValue(){
this.value = 0;
}
public void setValue(int v){
this.value = v;
}
How about this method? Would it still be considered overloading since it's returning a different data type?
public int setValue(){
return this.value;
}
Second question is: what is overriding
in java? Does it relate to inheritance. Let's I have the following:
public class Vehicle{
double basePrice = 20000;
//constructor defined
public double getPrice(){
return basePrice;
}
}
public class Truck extends Vehicle{
double truckPrice = 14000;
//constructor defined
public double getPrice(){
return truckPrice;
}
}
So now let's say I have the following
Truck truck = new Truck();
if I call
truck.super.getPrice()
this would return the price from the Vehicle class, 20,000
if I call
truck.getPrice()
this would return the price in the truck class, 14,000
Is my knowledge correct for both questions?
You are basically correct. Overloading is having multiple methods in a single class where the method has the same name. However, the return value is not seen as part of the signature of the method. Thus, you cannot overload a method by changing only the return value. You cannot have the following code, from your example:
public void setValue() {
this.value = 0;
}
public int setValue() {
return this.value;
}
This will fail to compile.
As Rob identified, I believe you mean overriding, and you have that correct. Note with overriding, you cannot change the return type. As of Java 5, you can return a derived type of what the base class method returned. Before Java 5, it must be the identical type. That is, you cannot do the below until Java 5 and later:
public class AnimalNoise {}
public class Miaw extends AnimalNoise {}
public class Animal {
public AnimalNoise makeNoise() {
return new AnimalNoise();
}
}
public class Cat extends Animal {
public Miaw makeNoise() {
return new Miaw ();
}
}
However, even in Java 5 and later, you cannot do the following:
public class Animal {
public String makeNoise() {
return "silence";
}
}
public class Cat extends Animal {
public Miaw makeNoise() {
return new Miaw ();
}
}
public class Miaw {}
Finally, a big difference between overloading and overriding that is often overlooked is that overloading is decided at compile time and overriding is decided at runtime. This catches many people by surprise when they expect overloading to be decided at runtime.
Correct; overloading is providing multiple signatures for the same method.
Overriding, which is what I think you mean by "overwriting" is the act of providing a different implementation of a method inherited from a base type, and is basically the point of polymorphism by inheritance, i.e.
public class Bicycle implements Vehicle {
public void drive() { ... }
}
public class Motorcycle extends Bicycle {
public void drive() {
// Do motorcycle-specific driving here, overriding Bicycle.drive()
// (we can still call the base method if it's useful to us here)
}
}
what you have described is correct.
For more clarification take a look at polymorphism concept. The Wikipedia has a good article
http://en.wikipedia.org/wiki/Polymorphism#Computing
http://en.wikipedia.org/wiki/Polymorphism_in_object-oriented_programming

Categories