ISC Practicals and Theory - Detail to Bill (OOP)
Updated 21 Oct 2026
A telephone bill shows inheritance and polymorphism together: a base class Detail keeps the subscriber's name, address, number and rent, and a derived class Bill adds the number of calls and works out the amount payable. This version uses parameterised constructors with super(...), overrides amount() and display() in Bill, and lets main hold a Detail reference to a Bill object, so the Bill versions run.
Definition
Inheritance lets a derived class (class Bill extends Detail) take the data members and methods of a base class and add its own. A derived class constructor passes values to the base class constructor with super(...), which must be its first statement. A method written again in the derived class with the same name and parameters is redefined (overridden). When a base class reference holds a derived class object, the version of the method that runs is chosen by the object, not by the reference type. This is subclass polymorphism with dynamic binding.
The bill follows a slab rule. These figures are a sample set; a question paper states its own slabs and rates, so use the question's figures in place of these:
- the first 100 calls are free;
- calls 101 to 200 cost Rs 1.00 each;
- calls 201 to 300 cost Rs 1.20 each;
- calls beyond 300 cost Rs 1.50 each;
- a surcharge of 5% is added on (rent + call charge).
Bill amount = rent + call charge + surcharge. For example, with rent Rs 300 and 250 calls: call charge $= 100 \times 1.00 + 50 \times 1.20 = 160$, surcharge $= 5\%$ of $460 = 23$, bill $= 300 + 160 + 23 = 483$.
Rent and the number of calls must not be negative; otherwise the program prints INVALID INPUT.
Algorithm
main(in the driver classTest) readsname,addressandtelas lines, thenrent.- If
rentis negative,mainprintsINVALID INPUTand stops. mainreadscalls. If it is negative,mainprintsINVALID INPUTand stops.maincreates the object withDetail ob = new Bill(name, address, tel, rent, calls). TheBillconstructor callssuper(n, a, t, r), which sets the four base data members, and then setscalls.maincallsob.display(). Because the object is aBill, the overridingdisplay()ofBillruns:super.display()prints the name, address, telephone number and rent;callCharge()works out the call charge: 0 for up to 100 calls;(calls - 100) * 1.00up to 200;100 * 1.00 + (calls - 200) * 1.20up to 300; otherwise100 * 1.00 + 100 * 1.20 + (calls - 300) * 1.50;- the surcharge is
(rent + call charge) * 5 / 100; amount(), also overridden inBill, returns rent + call charge + surcharge, and is printed as the bill amount.
- Every money value is printed to 2 decimal places with
printf("%.2f").
Program
Detail holds the data and a basic amount() (just the rent), Bill overrides amount() and display(), and Test holds main.
import java.util.Scanner;
/* Base class: the details of a telephone subscriber. */
class Detail
{
String name; // name of the subscriber
String address; // address of the subscriber
String tel; // telephone number (kept as text, it is not used in arithmetic)
double rent; // monthly rent in rupees
/* Parameterised constructor.
n: name, a: address, t: telephone number, r: monthly rent. */
Detail(String n, String a, String t, double r)
{
name = n;
address = a;
tel = t;
rent = r;
}
/* Returns the amount payable: for a plain Detail this is just the rent. */
double amount()
{
return rent;
}
/* Prints the subscriber's details and the rent. */
void display()
{
System.out.println("Name : " + name);
System.out.println("Address : " + address);
System.out.println("Telephone : " + tel);
System.out.printf("Rent : Rs %.2f%n", rent);
}
}
/* Derived class: a Detail plus the calls made, from which the bill is worked out. */
class Bill extends Detail
{
int calls; // number of calls made in the month
final int SLAB = 100; // size of each slab of calls
final double RATE1 = 1.00; // Rs per call, calls 101 to 200
final double RATE2 = 1.20; // Rs per call, calls 201 to 300
final double RATE3 = 1.50; // Rs per call, beyond 300
final double TAXPER = 5.0; // surcharge percentage
/* Parameterised constructor: passes the first four values to the base class.
n: name, a: address, t: telephone number, r: rent, c: number of calls. */
Bill(String n, String a, String t, double r, int c)
{
super(n, a, t, r); // base class constructor sets name, address, tel, rent
calls = c;
}
/* Returns the charge for the calls, by slabs. */
double callCharge()
{
double ch; // call charge worked out below
if (calls <= SLAB) // first 100 calls are free
{
ch = 0;
}
else if (calls <= 2 * SLAB) // next 100 calls at RATE1
{
ch = (calls - SLAB) * RATE1;
}
else if (calls <= 3 * SLAB) // next 100 calls at RATE2
{
ch = SLAB * RATE1 + (calls - 2 * SLAB) * RATE2;
}
else // calls beyond 300 at RATE3
{
ch = SLAB * RATE1 + SLAB * RATE2 + (calls - 3 * SLAB) * RATE3;
}
return ch;
}
/* Overrides amount(): returns rent + call charge + surcharge. */
double amount()
{
double sub = rent + callCharge(); // amount before the surcharge
return sub + sub * TAXPER / 100;
}
/* Overrides display(): base class details first, then the bill. */
void display()
{
super.display();
double cc = callCharge(); // call charge
double sub = rent + cc; // rent + call charge
System.out.println("Calls : " + calls);
System.out.printf("Call charge : Rs %.2f%n", cc);
System.out.printf("Surcharge : Rs %.2f%n", sub * TAXPER / 100);
System.out.printf("Bill amount : Rs %.2f%n", amount());
}
}
/* Driver class: holds main. */
public class Test
{
/* Reads the data, checks it, and prints the bill through a Detail reference. */
public static void main(String args[])
{
Scanner sc = new Scanner(System.in); // reads the input
String name, address, tel; // subscriber's details
double rent; // monthly rent
int calls; // number of calls
System.out.print("Enter name: ");
name = sc.nextLine();
System.out.print("Enter address: ");
address = sc.nextLine();
System.out.print("Enter telephone number: ");
tel = sc.nextLine();
System.out.print("Enter monthly rent (Rs): ");
rent = sc.nextDouble();
if (rent < 0)
{
System.out.println("INVALID INPUT");
return;
}
System.out.print("Enter number of calls: ");
calls = sc.nextInt();
if (calls < 0)
{
System.out.println("INVALID INPUT");
return;
}
Detail ob = new Bill(name, address, tel, rent, calls); // base reference, derived object
ob.display(); // runs Bill's display(), because the object is a Bill
}
}Variable description table
| Variable | Data Type | Purpose |
|---|---|---|
name | String | Data member of Detail: name of the subscriber; also the local in main that holds the typed name |
address | String | Data member of Detail: address; also the local in main that holds the typed address |
tel | String | Data member of Detail: telephone number, kept as text; also the local in main |
rent | double | Data member of Detail: monthly rent in rupees; also the local in main that holds the typed rent |
n | String | Parameter of both constructors: name of the subscriber |
a | String | Parameter of both constructors: address |
t | String | Parameter of both constructors: telephone number |
r | double | Parameter of both constructors: monthly rent |
calls | int | Data member of Bill: number of calls made in the month; also the local in main |
c | int | Parameter of the Bill constructor: number of calls |
SLAB | int | Constant: size of each slab of calls (100) |
RATE1 | double | Constant: rupees per call for calls 101 to 200 |
RATE2 | double | Constant: rupees per call for calls 201 to 300 |
RATE3 | double | Constant: rupees per call beyond 300 |
TAXPER | double | Constant: surcharge percentage |
ch | double | Local in callCharge(): the call charge being worked out |
sub | double | Local in amount() and in display(): rent plus call charge, before the surcharge |
cc | double | Local in display(): the call charge returned by callCharge() |
sc | Scanner | Local in main: reads the input |
ob | Detail | Reference of the base class type in main, holding the Bill object |
args | String[] | Command-line arguments of main (not used) |
Sample input and output
Sample 1
Enter name: Asha Rao
Enter address: 12 MG Road
Enter telephone number: 9876543210
Enter monthly rent (Rs): 300
Enter number of calls: 250
Name : Asha Rao
Address : 12 MG Road
Telephone : 9876543210
Rent : Rs 300.00
Calls : 250
Call charge : Rs 160.00
Surcharge : Rs 23.00
Bill amount : Rs 483.00Sample 2
Enter name: Meena Iyer
Enter address: 7 Lake View
Enter telephone number: 2456789
Enter monthly rent (Rs): 200
Enter number of calls: 350
Name : Meena Iyer
Address : 7 Lake View
Telephone : 2456789
Rent : Rs 200.00
Calls : 350
Call charge : Rs 295.00
Surcharge : Rs 24.75
Bill amount : Rs 519.75Sample 3
Enter name: Kiran Shah
Enter address: 3 Hill Road
Enter telephone number: 5551234
Enter monthly rent (Rs): 300
Enter number of calls: 0
Name : Kiran Shah
Address : 3 Hill Road
Telephone : 5551234
Rent : Rs 300.00
Calls : 0
Call charge : Rs 0.00
Surcharge : Rs 15.00
Bill amount : Rs 315.00Sample 4
Enter name: Ravi Kumar
Enter address: 5 Park Street
Enter telephone number: 2234567
Enter monthly rent (Rs): 250
Enter number of calls: -3
INVALID INPUTDry run
Take the first sample: rent $= 300$, calls $= 250$. main creates new Bill("Asha Rao", "12 MG Road", "9876543210", 300.0, 250). In display() of Bill:
| Step | Test or statement | Value |
|---|---|---|
| 1 | callCharge(): calls <= 100, calls <= 200 | both false |
| 2 | calls <= 300 | true |
| 3 | ch = 100 * 1.00 + (250 - 200) * 1.20 | 160.0 |
| 4 | cc | 160.0 |
| 5 | sub = 300 + 160 | 460.0 |
| 6 | surcharge = 460 * 5 / 100 | 23.0 |
| 7 | amount(): sub = 460, returns 460 + 23 | 483.0 |
The output is the details from super.display() followed by 250, 160.00, 23.00 and 483.00, so the last line is Bill amount : Rs 483.00, as in the first sample run.
Variations
- Slabs by units "Write a program to compute an electricity bill from the units consumed using a slab rate, with a class for the consumer's details and a derived class for the bill."
- Minimum charge "Modify the bill so that a minimum amount is payable even when no calls are made."
- Abstract base class "Make the base class abstract with an abstract method
amount()and give the bill calculation in the derived class."