Day 44- Ever wondered how one class can use another class without inheriting it? That’s exactly what the Has-A relationship is all about. Instead of making one class do everything, we let classes work together. 🔹 What is Has-A relationship? Has-A means: One class contains another class as a part of it. It doesn’t inherit behavior, it simply uses another object to perform tasks. This helps in building clean and modular code. 🔹 Let’s understand with a simple example class Test { void play() { System.out.println("Executing play()......"); } } class Example { Test ref; Example(Test ref) { this.ref = ref; } } public class MainClass2 { public static void main(String[] args) { Test t1 = new Test(); Example e1 = new Example(t1); e1.ref.play(); } } 🔹 What’s happening here? • A Test object is created • That object is passed into Example • Example stores it using a reference (ref) • Then Example uses it to call play() 🔹 Why this is Has-A? Because: 👉 Example HAS-A Test object 👉 It is not extending Test 👉 It is simply using Test’s functionality 🔹 Type of relationship here This is Aggregation (Weak Has-A) ✔ The Test object exists independently ✔ It is created outside and passed into Example ✔ Both classes are loosely connected 🔹 Why this matters Using Has-A relationship helps in: • Better code structure • Reusability of classes • Loose coupling • Real-world modelling Instead of writing one big class, we design systems where objects collaborate. #Java #OOP #ObjectOrientedProgramming #JavaProgramming #Coding #Programming #SoftwareDevelopment #Developer #LearningInPublic #TechLearning #ComputerScience #CodingJourney #CodeNewbie #JavaDeveloper
Java Has-A Relationship Explained
More Relevant Posts
-
Day 9/30 – Abstraction and Shortest Path in DAG Day 9 of the challenge focused on learning another important pillar of Object Oriented Programming and solving a graph problem based on shortest paths. Today’s learning was about hiding unnecessary complexity in code and using graph ordering to calculate minimum distances efficiently. MERN / OOP Concepts – Abstraction Today I learned about Abstraction, one of the core pillars of Object-Oriented Programming. What is Abstraction: • Abstraction means hiding internal implementation details and showing only essential functionality • It helps users interact with features without needing to know how everything works internally How it is achieved in Java: • Abstract classes • Interfaces Why it matters: • Reduces complexity • Improves code readability • Makes systems easier to maintain and extend • Focuses on what an object does instead of how it does it Real-world example: • When driving a car, we use steering, brakes, and accelerator • We do not need to understand the engine internals to drive it Key takeaway: • Show only what is necessary, hide the rest DSA – Shortest Path in DAG Today I solved Shortest Path in Directed Acyclic Graph (DAG). Approach: • Build graph using adjacency list with weights • Perform Topological Sort of all nodes • Initialize distance array with infinity • Start source node distance as 0 • Process nodes in topological order • Relax all outgoing edges to update shortest distances Key insight: • Since DAG has no cycles, topological order guarantees that each node is processed after its dependencies • This makes shortest path faster than Dijkstra in DAG cases Why this problem is important: • Combines Topological Sort with shortest path logic • Shows how graph structure can optimize solutions Time Complexity: O(V + E) Space Complexity: O(V + E) Takeaways • Abstraction helps simplify complex systems • Good software design hides unnecessary details • DAG problems often become easier using topological order • Choosing the right graph technique can greatly improve efficiency Day 9 completed. Concepts are getting deeper, and patterns are becoming more natural. #30DaysChallenge #OOP #Abstraction #Java #DSA #Graphs #ShortestPath #Consistency #LearningInPublic
To view or add a comment, sign in
-
-
Day 24 of #100DaysOfCode I stared at this problem for 40 minutes trying every possible target value. Then one insight — borrowed from basic statistics — made it click instantly. 🧩 The Problem: Minimum Operations to Make a Uni-Value Grid (LeetCode 2033 — Medium) Given a 2D grid and a fixed step value x, transform every element to the same value using the minimum number of add/subtract operations. My first instinct? Try every possible target. Loop through everything. Classic overthinking. 😅 💡 The Key Insight — Why the Median? The median minimizes the sum of absolute differences. This is a well-known statistics fact — and it maps perfectly to this problem. Instead of brute-forcing every target, the strategy is simple: → Flatten the 2D grid into a 1D array → Sort it → Pick the middle element (median) as the target → Count total operations using the absolute difference divided by x No guessing. No unnecessary loops. Just math doing the heavy lifting. ⚠️ The Constraint Check Nobody Talks About Before applying any operations — check if all elements share the same remainder when divided by x. If they don't, it's mathematically impossible to make the grid uni-value. Return -1 immediately and save the computation entirely. This "fail fast" mindset is just as important as the algorithm itself. 📈 Complexity Breakdown → Flatten + Sort → O(n log n) → Single pass to count operations → O(n) → Space → O(n) for the flattened array Simple, clean, and efficient. 🧠 What This Problem Reinforced ✅ Greedy thinking with median optimization ✅ Handle impossible cases before computation — fail fast ✅ Transform 2D problems into simpler 1D forms ✅ Let math do the heavy lifting before writing a single loop The best solutions often come from asking: "What does math already know about this?" On to the next challenge 💪 👇 What's a problem where a simple insight saved you from overcomplicating things? Drop it in the comments — would love to learn from your experience! #100DaysOfCode #LeetCode #DSA #Java #ProblemSolving #CodingJourney #SoftwareEngineering #Programming
To view or add a comment, sign in
-
-
🚀 Solved LeetCode Problem #47 – Permutations II Today I tackled a classic backtracking problem that adds an interesting twist—handling duplicate elements while generating permutations. 🔍 Problem Insight: Given an array that may contain duplicates, the goal is to generate all unique permutations without repetition. 💡 Approach Used: I used a Backtracking + Sorting strategy: First, sort the array to bring duplicates together Use a visited[] array to track used elements Apply a smart condition to skip duplicate choices during recursion This ensures that we only generate distinct permutations efficiently. 🧠 Key Learning: Handling duplicates in recursive problems is crucial Sorting helps simplify duplicate detection Backtracking becomes powerful when combined with pruning conditions 📈 Complexity: Time: O(n!) Space: O(n) ✨ This problem strengthened my understanding of: Backtracking techniques Recursion control and pruning Writing optimized solutions for combinatorial problems Consistency in solving such problems is helping me build stronger problem-solving skills every day! 💪 #LeetCode #DSA #Backtracking #Algorithms #Coding #ProblemSolving #Java #TechJourney
To view or add a comment, sign in
-
-
🚀 Solved “Search Insert Position” using Binary Search on LeetCode! Today I worked on an interesting problem where the goal is to find the index of a target element in a sorted array. If the target is not present, we return the index where it should be inserted to maintain sorted order. 🔍 Approach: Instead of using a linear search (O(n)), I implemented an efficient Binary Search (O(log n)) approach. 💡 Key Learning: One important detail is calculating the middle index safely: mid = low + (high - low) / 2 This avoids potential integer overflow compared to (low + high) / 2 and ensures correct behavior even for large inputs. ⚙️ Logic: If target == arr[mid] → return mid If target > arr[mid] → search right half Else → search left half If not found → return ‘low’ as the correct insert position 📈 Result: Achieved 100% performance on LeetCode 🚀 This problem reinforced my understanding of: ✔ Binary Search fundamentals ✔ Edge case handling ✔ Writing optimized and safe code Looking forward to solving more problems and improving problem-solving skills! #LeetCode #BinarySearch #Java #DataStructures #Coding #ProblemSolving
To view or add a comment, sign in
-
-
🚀 Day 26 – Mastering Polymorphism (OOP Made Simple) Today I learned one of the most powerful concepts in OOP — Polymorphism (Many Forms). 👉 Definition: One method call can perform different actions depending on the object. Example: ref.takeOff() ✔ CargoPlane ✔ PassengerPlane ✔ FighterPlane Same method → Different behavior 🔥 ✈️ Plane Example (Real Understanding) We have a parent class Plane with methods: takeOff() fly() land() Child classes override these methods: CargoPlane PassengerPlane FighterPlane Each plane behaves differently 👇 🔴 Tight Coupling (Not Good) CargoPlane cp = new CargoPlane(); cp.takeOff(); ❌ No flexibility ❌ No real polymorphism 🟢 Loose Coupling (Best Practice) Plane ref = new CargoPlane(); ref.takeOff(); ✔ Flexibility ✔ Polymorphism achieved 🔼 Upcasting Child → Parent Plane ref = new CargoPlane(); 🔽 Downcasting Parent → Child ((CargoPlane) ref).carryCargo(); 📌 Important Rule Using Parent Reference: ✔ Can call inherited methods ✔ Can call overridden methods ❌ Cannot call specialized methods 🏢 Code Optimization Example class Airport { void permit(Plane ref) { ref.takeOff(); ref.fly(); ref.land(); } } Usage: a.permit(new CargoPlane()); a.permit(new PassengerPlane()); a.permit(new FighterPlane()); ✔ Same method works for all ✔ Less code, more power 💯 🎯 Advantages of Polymorphism ✅ Code Reduction ✅ Code Flexibility ✅ Reusability 🧠 Easy Memory Trick ✔ Child → Parent = Upcasting ✔ Parent → Child = Downcasting ✔ Tight Coupling = Same type reference + object ✔ Loose Coupling = Parent reference + child object 💡 Final Thought: "Write code once, use it many ways" — that’s the real power of Polymorphism. #Java #OOP #Polymorphism #CodingJourney #LearningInPublic #SoftwareEngineering #Day26
To view or add a comment, sign in
-
-
🚀 Day 54 of My LeetCode Journey 🔍 Problem: Find the Index of the First Occurrence in a String Today’s problem focused on searching for a substring inside a string — a very common concept in interviews and real-world applications like text processing and search engines. 💡 Key Idea: We compare the substring (needle) with every possible starting position in the main string (haystack) until we find a match. 🧠 What I Learned: How string matching works internally Importance of boundary conditions (like empty strings) Difference between brute-force and optimized approaches Why built-in methods like indexOf() are efficient ⚡ Approaches: Using built-in method (indexOf) – simple and efficient Manual iteration (brute force) – helps understand logic deeply 📈 Time Complexity: O(n * m) for brute-force approach 🔥 Takeaway: Even simple problems can teach core fundamentals. Mastering these basics builds a strong foundation for advanced algorithms like KMP. #Day54 #LeetCode #Java #DataStructures #CodingJourney #Programming #InterviewPreparation
To view or add a comment, sign in
-
-
Is your code getting lost in a maze of nested `if` statements? 😵💫 There's a cleaner path to more readable and maintainable functions. We've all been there: functions riddled with deeply indented conditional logic, making it tough to follow the "happy path" and spot crucial edge cases. This "arrow code" significantly increases cognitive load and can quickly become a source of subtle bugs. One of my favorite patterns for dramatically improving readability and maintainability is using **Guard Clauses** (or Early Exits). Instead of wrapping your core logic in multiple `if` blocks, you validate conditions at the start of your function and return early if any prerequisites aren't met. This simple refactoring flattens your code, making the primary flow much clearer. It pushes error handling and invalid state checks to the forefront, allowing your main business logic to live in a clean, unindented section. It's a huge win for developer experience and often prevents subtle bugs by handling invalid states upfront. Here's a quick Python example demonstrating the power of guard clauses: ```python # Before (nested ifs) def process_order_old(order): if order: if order.is_valid(): if order.items: # Core processing logic return "Order processed successfully." else: return "Error: Order has no items." else: return "Error: Order is invalid." else: return "Error: Order is None." # After (using Guard Clauses) def process_order_new(order): if not order: return "Error: Order is None." if not order.is_valid(): return "Error: Order is invalid." if not order.items: return "Error: Order has no items." # Core processing logic (clean, unindented) return "Order processed successfully." ``` The takeaway here is simple: prioritize clear, linear code paths. Guard clauses help you achieve this, pushing error handling to the front and letting your main logic shine, boosting both productivity and code quality. What's your go-to refactoring technique for improving code readability and maintainability? Share your tips below! 👇 #Programming #CodingTips #SoftwareEngineering #Python #CleanCode #Refactoring #DeveloperExperience
To view or add a comment, sign in
-
🚀 Day 75 — Slow & Fast Pointer (Happy Number Detection) Extending the slow‑fast pointer pattern beyond linked lists — today I applied it to a mathematical problem involving cycles. 📌 Problem Solved: - LeetCode 202 – Happy Number 🧠 Key Learnings: 1️⃣ The Problem in a Nutshell A number is happy if repeatedly replacing it with the sum of squares of its digits eventually reaches 1. If it enters a cycle that doesn’t include 1, it’s unhappy. 2️⃣ Why Slow‑Fast Pointer Works - The sequence of numbers (n → sum of squares of digits → ...) will eventually either reach 1 or enter a cycle. - This is exactly like detecting a cycle in a linked list — except the “next” is defined mathematically. - Slow moves one step: `slow = sq(slow)` - Fast moves two steps: `fast = sq(sq(fast))` - If they meet at a value other than 1 → cycle exists → unhappy number. - If fast reaches 1 → happy number. 3️⃣ The sq() Helper Computes sum of squares of digits. Clean and reusable. 4️⃣ Edge Cases - n = 1 → returns true immediately (loop condition `fast != 1` fails, returns true). - Numbers like 2, 3, 4 eventually cycle (4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4). 💡 Takeaway: The slow‑fast pointer pattern isn’t just for linked lists — it’s a general cycle detection tool that works for any sequence with a deterministic “next” step. Recognizing this abstraction is what makes a great problem solver. No guilt about past breaks — just one problem at a time, one pattern at a time. #DSA #SlowFastPointer #HappyNumber #CycleDetection #LeetCode #CodingJourney #Revision #Java #ProblemSolving #Consistency #GrowthMindset #TechCommunity #LearningInPublic
To view or add a comment, sign in
-
Day 7/30 – Encapsulation and Graph Safety States Day 7 of the challenge focused on strengthening OOP fundamentals and solving another important graph problem. Today’s learning was about writing secure, maintainable code through encapsulation and understanding reverse graph logic in DSA. MERN / OOP Concepts – Encapsulation Today I learned about Encapsulation, one of the core pillars of Object Oriented Programming. What is Encapsulation: • Binding data and methods together inside a single unit (class) • Restricting direct access to object data using access modifiers How it works: • Variables are usually marked as private • Public getter and setter methods are used to access or update values safely Why it matters: • Protects data from unwanted modification • Improves code security and maintainability • Gives better control over how data is handled Real world example: • A bank account balance should not be modified directly • It should only change through deposit or withdraw methods Key takeaway: • Encapsulation is about data hiding and controlled access DSA – Find Eventual Safe States Today I solved Find Eventual Safe States, a graph problem based on cycles and topological sorting. Approach: • Reverse all graph edges • Calculate outdegree of each node • Nodes with outdegree 0 are terminal nodes and considered safe • Add them to queue • Process using BFS and reduce outdegree of connected nodes • Nodes that become outdegree 0 are also safe Key insight: • Nodes leading to cycles are unsafe • Nodes eventually reaching terminal nodes are safe Why reverse graph helps: • Makes it easier to process dependencies backward Time Complexity: O(V + E) Space Complexity: O(V + E) Takeaways • Encapsulation helps build clean and secure object-oriented code • Controlled access to data prevents many bugs • Graph problems often become easier after reversing perspective • Topological thinking is useful beyond DAG problems Day 7 completed. One more day of consistency, one more step of growth. #30DaysChallenge #OOP #Encapsulation #Java #DSA #Graphs #TopologicalSort #Consistency #LearningInPublic
To view or add a comment, sign in
-
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development
Really clean explanation 👍Has-A is something that feels simple but becomes powerful when we design real systems.In most backend projects, we use this pattern heavily for loose coupling and better testability (like injecting services into controllers). One thing I realized later is: composition (Has-A) often scales much better than inheritance in large applications.