HackIndia Logo
HackathonsNewsSkillsGrowth
HackIndia LogoContact: +91 9910125804

General

  • Companies
  • Colleges
  • Board of Advisors
  • Brand Ambassadors
  • FAQ
  • Contact
  • Report a Bug

Hackathons

  • Upcoming Hackathons
  • Judges
  • Mentors
  • Partners
  • Participating Colleges
  • Testimonials

Resources

  • About Us
  • Branding
  • Latest News
  • Growth
  • Skills
  • Builders
  • Ecosystem
  • Forum
  • Ideas
  • Prompt Optimizer
  • Games

© 2026 HackIndia. All rights reserved.

Privacy PolicyTerms of ServiceCode of ConductSitemap

Build 2.139 · 05 Nov 2026, 10:27 UTC

    HackIndia
    HackathonsNewsInternshipsSkillsGrowthPro Perks
    ← Model features with objects

    All the reading

    OOP

    7 lessons, about 30 minutes. The check's questions come from these.

    Contents
    Finding objects from features
    1. 1. Objects that solve features
    Classes, state, and encapsulation
    1. 2. Classes, objects, and state
    2. 3. Encapsulation without overengineering
    Composition, interfaces, and SOLID
    1. 4. Composition before inheritance
    2. 5. Polymorphism through interfaces
    3. 6. SOLID in plain words
    4. 7. Build and submit your repo

    Finding objects from features

    1. Objects that solve features

    4 min

    In 30 seconds
    • Pick a feature and name the objects that make it work.
    • Separate real domain objects from screens, buttons, and database tables.
    • Write a tiny object model note that a recruiter can understand.
    Key point

    One idea

    OOP starts with a feature, not with a class list. First ask: what real things take part in this feature, and what work does each thing do?

    Start from behaviour

    A recruiter will not be impressed by a random Student class with getters and setters. They want to see code that solves a small real problem clearly.

    Pick a feature you can explain in one line. For example: split a canteen bill, book a lab slot, track hostel laundry, or manage club event registrations.

    Your to-do

    Find your objects

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Worked example

    Feature: students split a chai and snacks bill after a club meeting.

    Useful objects are Bill, BillItem, Member, and Split. The button called Pay Now is not a domain object. A payments table is not your starting point.

    Feature: Split a canteen bill between members
    
    Objects:
    - Bill: holds items and members, calculates total
    - BillItem: stores name, price, quantity
    - Member: stores name and amount paid
    - Split: calculates what each member owes
    
    Not objects yet:
    - SplitBillScreen
    - Pay Now button
    - bill_items database table

    Classes, state, and encapsulation

    2. Classes, objects, and state

    4 min

    In 30 seconds
    • Turn a feature idea into a class with fields and methods.
    • Create objects with different state from the same class.
    • Avoid shared state bugs that make OOP code hard to test.
    Key point

    One idea

    A class is the plan. An object is one real thing made from that plan, with its own state.

    State is the data an object remembers between method calls. Methods should change or read that state for a clear feature reason.

    Feature first

    Do not start with a class named Manager, Helper, or Utils. Start with a feature sentence.

    Example: “A student can add expenses and see the total split for a hostel trip.” This suggests objects like Trip and Expense because they are real parts of the feature.

    Example

    Class to object

    Here is a small Python example. One Trip class can create many trip objects. Each trip keeps its own expenses.

    Composition, interfaces, and SOLID

    4. Composition before inheritance

    4 min

    In 30 seconds
    • Choose composition when a feature is made of parts working together.
    • Replace fragile parent classes with small objects that each do one job.
    • Refactor one class into composed collaborators you can explain in a README.
    Key point

    One idea

    Prefer composition when your object “has a” helper or part. Use inheritance only when your object truly “is a” specialised version of another object.

    Composition keeps your feature easier to change. You can replace one part without rewriting the whole class.

    Why this matters

    In hackathon code, inheritance often starts clean and becomes confusing by demo day. A base class gets too many methods because every child needs something slightly different.

    Composition avoids that. You build small classes and pass them into the feature class. The main class coordinates them.

    Common mistake

    10 questions, 7 to pass.

    Sign in to take the test
    Common mistake

    Common mistake

    Beginners often copy database tables into classes. This makes code look object-oriented, but the logic still lives outside the objects.

    If your class only stores data and another file does all the work, pause. Ask which object should own that behaviour.

    Tip

    Use AI carefully

    You can ask ChatGPT, Gemini, or Claude to suggest objects for your feature. Do not accept the first list blindly.

    Check three things: are the objects from the problem, does each object have a clear responsibility, and did the AI add big-enterprise classes you do not need?

    Prompt:
    I am building a small OOP feature for a college project.
    Feature: Split a canteen bill between 4 students.
    Suggest domain objects only. Avoid UI, database, framework, and overengineered classes.
    For each object, give one responsibility and 2-3 methods.
    
    Check the answer:
    - Remove Manager, Service, Controller unless you truly need them
    - Keep names a non-technical user can understand
    - Keep the feature small enough to build and test this week

    What good looks like

    Your first object model can be small. Three to five objects are enough for lesson 1.

    Good object names make your README easier to read. If a senior can understand your feature without running the code, you are on the right track.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    class Trip:
        def __init__(self, name):
            self.name = name
            self.expenses = []
    
        def add_expense(self, paid_by, amount, note):
            self.expenses.append({
                "paid_by": paid_by,
                "amount": amount,
                "note": note
            })
    
        def total_amount(self):
            total = 0
            for expense in self.expenses:
                total += expense["amount"]
            return total
    
    manali_trip = Trip("Manali")
    goa_trip = Trip("Goa")
    
    manali_trip.add_expense("Asha", 1200, "bus booking")
    goa_trip.add_expense("Ravi", 800, "scooter rent")
    
    print(manali_trip.total_amount())  # 1200
    print(goa_trip.total_amount())     # 800

    What state means

    In this example, name and expenses are state. They belong to each Trip object.

    manali_trip and goa_trip use the same class, but their state is different. That is why changing one trip does not change the other.

    Common mistake

    Shared state bug

    A common bug is placing changeable state on the class instead of the object. Then all objects may accidentally share the same list.

    If a list or dictionary should be different per object, create it inside the constructor.

    class BadTrip:
        expenses = []  # shared by every BadTrip object
    
        def __init__(self, name):
            self.name = name
    
    class GoodTrip:
        def __init__(self, name):
            self.name = name
            self.expenses = []  # separate list for each object
    Your to-do

    Model a small feature

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Tip

    Use AI carefully

    You can ask ChatGPT or Gemini: “Suggest classes, state, and methods for this feature. Keep it simple.”

    Check the answer. Remove vague classes like Manager. Keep only classes that store useful state or perform a clear feature action.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    3. Encapsulation without overengineering

    4 min

    In 30 seconds
    • Hide the data that should not be changed directly.
    • Expose small methods that match the feature’s real actions.
    • Avoid getters, setters, and layers that do not protect anything.
    Key point

    One idea

    Encapsulation means your object protects its own rules. Other code should ask the object to do a valid action, not reach inside and edit its state.

    Why it matters

    In a hackathon repo, recruiters do not expect a huge design. They look for code where bugs are harder to create.

    If anyone can change every field, your class is just a loose data bag. A small method like markPaid() or assignDriver() can check rules before state changes.

    Example

    Bad shape

    This looks simple, but any part of the app can put the order into a wrong state. You can mark it paid with zero amount. You can set any random status string.

    class FoodOrder:
        def __init__(self, order_id, total_rupees):
            self.order_id = order_id
            self.total_rupees = total_rupees
            self.status = "CREATED"
            self.paid = False
    
    order = FoodOrder("ORD-17", 0)
    order.paid = True
    order.status = "DONE_DONE"
    Example

    Better shape

    Keep fields private by convention, then expose methods for real actions. This version is still small. No framework. No extra pattern.

    class FoodOrder:
        VALID_STATUSES = {"CREATED", "PAID", "CANCELLED"}
    
        def __init__(self, order_id, total_rupees):
            if total_rupees <= 0:
                raise ValueError("Order total must be more than 0")
            self._order_id = order_id
            self._total_rupees = total_rupees
            self._status = "CREATED"
    
        def mark_paid(self):
            if self._status == "CANCELLED":
                raise ValueError("Cancelled order cannot be paid")
            self._status = "PAID"
    
        def cancel(self):
            if self._status == "PAID":
                raise ValueError("Paid order cannot be cancelled here")
            self._status = "CANCELLED"
    
        def summary(self):
            return {
                "order_id": self._order_id,
                "total_rupees": self._total_rupees,
                "status": self._status
            }
    
    order = FoodOrder("ORD-17", 199)
    order.mark_paid()
    print(order.summary())
    Your to-do

    Encapsulate a class

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Common mistake

    Getter setter trap

    Do not create getStatus() and setStatus() for every field by habit. That often gives public access with extra typing.

    Use a setter only when outside code is allowed to change that value directly. If there is a rule, name the method after the action and enforce the rule there.

    Tip

    Use AI safely

    You can ask ChatGPT or Gemini: “Given this class, which fields should be private and what methods should change them?” Then check the answer yourself.

    Reject suggestions that add abstract factories, managers, or service layers for a tiny feature. For this lesson, one clear class with protected rules is enough.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Common wrong turn

    Do not create a parent class just because two classes share one or two lines of code. Shared code is not always a parent-child relationship.

    For example, a FoodOrder and a CabRide may both have a price. That does not mean both should inherit from BillableThing. They may just use the same PriceCalculator.

    Example

    Inheritance version

    This looks fine at first. But every new payment type can force changes in the parent class. The parent starts knowing too much.

    class Order:
        def __init__(self, amount):
            self.amount = amount
    
        def pay_by_upi(self, upi_id):
            print(f"Paid ₹{self.amount} using UPI: {upi_id}")
    
        def pay_by_card(self, card_last4):
            print(f"Paid ₹{self.amount} using card ending {card_last4}")
    
    
    class FoodOrder(Order):
        def __init__(self, amount, restaurant_name):
            super().__init__(amount)
            self.restaurant_name = restaurant_name
    Example

    Composition version

    Here, FoodOrder has a payment method. It does not inherit payment behaviour. It uses another object to do that job.

    This is easier to test. You can test FoodOrder separately from UPI payments.

    class UpiPayment:
        def __init__(self, upi_id):
            self.upi_id = upi_id
    
        def pay(self, amount):
            return f"Paid ₹{amount} using UPI: {self.upi_id}"
    
    
    class FoodOrder:
        def __init__(self, amount, restaurant_name, payment_method):
            self.amount = amount
            self.restaurant_name = restaurant_name
            self.payment_method = payment_method
    
        def checkout(self):
            return self.payment_method.pay(self.amount)
    
    
    payment = UpiPayment("student@oksbi")
    order = FoodOrder(249, "Campus Canteen", payment)
    print(order.checkout())
    Your to-do

    How to decide

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Tip

    Use AI carefully

    You can ask ChatGPT or Gemini: “Refactor this class to prefer composition over inheritance. Keep the same behaviour.” Then check the answer yourself.

    Check that the new small classes have clear jobs, the main feature class is still readable, and the code still runs with the same sample input.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    5. Polymorphism through interfaces

    5 min

    In 30 seconds
    • Use an interface when one action has many possible implementations.
    • Write feature code that depends on behavior, not a specific class.
    • Add a new option without editing the main flow.
    Key point

    One idea

    Polymorphism means your code can call the same method on different objects, and each object does the work in its own way.

    An interface is a small contract for that method. Your main feature talks to the contract, not to one exact class.

    Why it helps

    In a real app, choices change. A canteen app may collect payment by UPI today, wallet tomorrow, and cash at the counter during a college fest.

    If your order code directly depends on UPI code, every new payment type will force you to edit order code. Interfaces stop that spread.

    Your to-do

    When to use it

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Payment example

    Here is a small Java example. The OrderService does not know whether payment is UPI or cash. It only knows that payment can be paid.

    This makes the feature easy to extend and easy to test.

    interface PaymentMethod {
        boolean pay(int amountInRupees);
    }
    
    class UpiPayment implements PaymentMethod {
        private final String upiId;
    
        UpiPayment(String upiId) {
            this.upiId = upiId;
        }
    
        public boolean pay(int amountInRupees) {
            System.out.println("Collecting Rs " + amountInRupees + " using UPI: " + upiId);
            return true;
        }
    }
    
    class CashPayment implements PaymentMethod {
        public boolean pay(int amountInRupees) {
            System.out.println("Collect Rs " + amountInRupees + " at counter");
            return true;
        }
    }
    
    class OrderService {
        private final PaymentMethod paymentMethod;
    
        OrderService(PaymentMethod paymentMethod) {
            this.paymentMethod = paymentMethod;
        }
    
        void placeOrder(int amountInRupees) {
            boolean paid = paymentMethod.pay(amountInRupees);
            if (paid) {
                System.out.println("Order placed");
            }
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            PaymentMethod payment = new UpiPayment("student@upi");
            OrderService orderService = new OrderService(payment);
            orderService.placeOrder(120);
        }
    }
    Tip

    Use AI carefully

    Ask an AI tool to suggest interfaces only after you describe the feature in plain words. Example: “In my canteen app, orders can be paid by UPI or cash. Suggest a small interface and classes in Java.”

    Check that the AI does not create huge interfaces with many unrelated methods. A good interface is narrow. One job is enough.

    Common mistake

    Common mistake

    Do not create an interface for every class. That only adds files without making the feature easier to change.

    Use an interface when your feature has real variation, or when you need to swap a dependency in tests. If there is only one stable class, a class is fine.

    Show it in your repo

    For your HackIndia project, make the interface visible in your object model. A recruiter should be able to open your code and see the contract, the implementations, and the feature class that uses the contract.

    In your README, write one short line like: “OrderService depends on PaymentMethod, so we can add new payment types without changing order placement logic.”

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    6. SOLID in plain words

    4 min

    In 30 seconds
    • Use SOLID as five checks for cleaner OOP choices.
    • Spot when a class, interface, or dependency is doing too much.
    • Make one small refactor that improves your feature repo.
    Key point

    One idea

    SOLID is not a rulebook to impress seniors. It is a set of checks that helps your feature stay easy to change without breaking everything else.

    Use it after you have working code. First ship the feature. Then clean the design where change is likely.

    The five checks

    S means Single Responsibility. A class should have one main reason to change. For example, Order should not also send WhatsApp messages and write invoices.

    O means Open/Closed. Add a new behaviour by adding a new class when possible, not by editing one big if-else block every time.

    The next three

    L means Liskov Substitution. If code expects a PaymentMethod, any UpiPayment or CardPayment should work without surprise errors.

    I means Interface Segregation. Do not force a class to implement methods it does not need. D means Dependency Inversion. High-level code should depend on interfaces, not hard-coded concrete classes.

    Example

    Small payment example

    Here is a simple Dependency Inversion and Open/Closed example. Checkout uses the PaymentMethod interface. Adding NetBankingPayment later will not require changing Checkout.

    interface PaymentMethod {
      boolean pay(int amountInRupees);
    }
    
    class UpiPayment implements PaymentMethod {
      public boolean pay(int amountInRupees) {
        System.out.println("Paid ₹" + amountInRupees + " using UPI");
        return true;
      }
    }
    
    class Checkout {
      private final PaymentMethod paymentMethod;
    
      Checkout(PaymentMethod paymentMethod) {
        this.paymentMethod = paymentMethod;
      }
    
      boolean placeOrder(int amountInRupees) {
        return paymentMethod.pay(amountInRupees);
      }
    }
    
    class Main {
      public static void main(String[] args) {
        Checkout checkout = new Checkout(new UpiPayment());
        checkout.placeOrder(499);
      }
    }
    Common mistake

    Do not over-SOLID

    Beginners sometimes create ten interfaces for a two-class feature. That makes the repo harder to read, not better.

    Use SOLID to remove pain. If there is only one implementation and no likely change, a direct class may be fine.

    Tip

    Use AI carefully

    Ask an AI tool to review your object model using SOLID. Then check the advice yourself. AI often suggests extra abstractions you do not need.

    A useful prompt: Review these classes for SOLID issues. Suggest only changes that make the feature easier to test or extend. Avoid adding patterns unless needed.

    Your to-do

    SOLID review pass

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    7. Build and submit your repo

    5 min

    In 30 seconds
    • Prepare a public repo that proves one OOP feature works.
    • Add tests or sample runs so a reviewer can verify it fast.
    • Write a short README that explains your object model clearly.
    Key point

    Proof beats claims

    Your repo is the proof. A recruiter should see the feature, run it, and understand your object model in a few minutes.

    Do not submit only class diagrams or copied notes. Submit working code with a small, real feature.

    Pick one feature

    Choose a feature small enough to finish and large enough to show objects working together. Think hostel room booking, UPI expense split, canteen order billing, event registration, or library fine calculation.

    Your feature should have 3 to 6 classes. It should show composition, interfaces, or clear SOLID choices from earlier lessons.

    Your to-do

    Repo checklist

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    README starter

    Use a short README. Avoid long theory. Explain the model like you would to a senior in your college coding club.

    # Canteen Order Billing
    
    ## Feature
    Calculates the bill for a canteen order with items, quantities, taxes, and payment method charges.
    
    ## Object model
    - MenuItem stores item name and price.
    - OrderLine combines a MenuItem with quantity.
    - Order contains many OrderLine objects and calculates subtotal.
    - PaymentMethod is an interface for payment-specific charges.
    - UpiPayment and CardPayment implement PaymentMethod.
    - BillService uses Order and PaymentMethod to create the final bill.
    
    ## How to run
    python main.py
    
    ## Sample output
    Subtotal: 120
    Payment charge: 0
    Total: 120
    
    ## Why this is OOP
    The feature uses composition because Order has OrderLine objects.
    PaymentMethod keeps payment rules separate from billing logic.
    Tip

    Use AI carefully

    You can ask ChatGPT, Gemini, or Claude to review your README and object model. Ask for clarity, not for fake complexity.

    Check every suggestion. Remove extra patterns, unused classes, and words you cannot explain in an interview.

    Prompt:
    Review this README for a beginner-friendly OOP project. Tell me if the object model is clear, if any class looks unnecessary, and if the run steps are missing anything.
    
    Paste README here.
    Common mistake

    Do not hide failure

    A repo with code but no way to run it feels unfinished. A repo with a broken command wastes the reviewer’s time.

    Before you submit, clone your own repo into a fresh folder and run the exact README steps. If it fails there, fix the README or the code.

    Your to-do

    Submit on HackIndia

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done