Object-oriented – Java subclass instance writer

I have written a relatively small abstract class in Java that tracks all instances of its subclasses. Any class that extends this abstract class will automatically have all of its instances stored (through a weak reference) in a Set, which can be retrieved if a subclass ever wants to get references to all its instances.

Although this class is relatively short and simple, I have never done anything like that and, therefore, I want to make sure that I am not doing something terribly wrong or that I am not giving in to bad practices:

import java.util.*;

public abstract class InstanceRecorder {
    private static Map, Set> instances;

    static {
        instances = new HashMap<>();
    }

    {
        instances.putIfAbsent(this.getClass(), Collections.newSetFromMap(new WeakHashMap<>()));
        instances.get(this.getClass()).add(this);
    }

    protected static int countInstances(Class key) {
        if (instances.containsKey(key))
            return instances.get(key).size();
        return 0;
    }

    @SuppressWarnings("unchecked")
    protected static  Set getInstances(Class key) {
        if (instances.containsKey(key))
            return Collections.unmodifiableSet((Set) instances.get(key));
        return new HashSet<>();
    }
}

As I said before, I had never done a class like this before, so any comment or idea would be greatly appreciated.

Object-oriented – Python – Options to access class attributes / methods from other classes while maintaining encapsulated classes?

I am teaching Python and I am working on a clone of space invaders. Virtually everything works as I want. But I am also trying to teach myself good principles of object-oriented design.

I have an AlienInvasion class that initializes a lot of game objects and runs the while cycle for the game (currently it also does some other things that should probably be in its own classes). When I create each object, I pass the AlienInvasion object so that each class can access the objects with which it needs to interact. For example, here is a class that searches and responds to events:

import sys

import pygame


class EventHandler:

    def __init__(self, ai_game):
        """Initialize attributes."""
        self.ai_game = ai_game
        self.settings = ai_game.settings
        self.display = ai_game.display
        self.stats = ai_game.stats
        self.sb = ai_game.sb
        self.ship = ai_game.ship

    def check_events(self):
        """Respond to keypresses and mouse events."""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.sb.record_high_score()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                self._check_button(mouse_pos)

    def _check_keydown_events(self, event):
        """Respond to keypresses."""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = True
        elif event.key == pygame.K_q:
            self.ai_game.quit()
        elif event.key == pygame.K_SPACE:
            self.ship.fire_bullet()
        elif event.key == pygame.K_e and not self.stats.game_active:
            self.settings.set_difficulty(self.settings.easy)
            self.ai_game.start_game()
        elif event.key == pygame.K_n and not self.stats.game_active:
            self.settings.set_difficulty(self.settings.normal)
            self.ai_game.start_game()
        elif event.key == pygame.K_h and not self.stats.game_active:
            self.settings.set_difficulty(self.settings.hard)
            self.ai_game.start_game()

    def _check_keyup_events(self, event):
        """Respond to key releases."""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        elif event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _check_button(self, mouse_pos):
        """Set the difficulty setting."""
        if self.display.easy_button.rect.collidepoint(mouse_pos):
            self.settings.set_difficulty(self.settings.easy)
            self.ai_game.start_game()
        elif self.display.normal_button.rect.collidepoint(mouse_pos):
            self.settings.set_difficulty(self.settings.normal)
            self.ai_game.start_game()
        elif self.display.hard_button.rect.collidepoint(mouse_pos):
            self.settings.set_difficulty(self.settings.hard)
            self.ai_game.start_game()
        elif self.display.quit_button.rect.collidepoint(mouse_pos):
            self.ai_game.quit()

The initialization method consists entirely of configuring attributes that refer to ai_game objects (the AlienInvasion class) so that EventHandler can tell each object when to do so in response to an event. This is how I have been handling all object interactions. The AlienInvasion class & # 39; knows & # 39; about all the different objects and allows each object to interact with other objects through the types of attributes you see above in EventHandler. This does not seem to me to be a good design in the sense that the objects in which they are (I think) are more coupled than they should be.

I am interested in learning how to make my code easier to maintain. I have spent the last days looking for an answer. I have not seen anything that explains how I should handle object interactions (or, more accurately, I have not seen anything that I recognize as something I could / should apply here to minimize how much & # 39; knows & # 39; each object on the other objects ). I have read some things about the attributes of inheritance, composition, mixins and class (instead of instance) and none of that seems correct here (quite possibly because I simply don't see how to apply any of the things that I have seen in correctly here).

I guess I'm essentially asking for a code review, but a design-oriented one.

You can see the complete code at https://github.com/nmoore32/Space-Invaders-Clone

Object-oriented – Small Java program for trainers, trains and engines

I have been trying to make a simple program in Java that involves trains, trainers and engines as a practice in OOP. I already have some knowledge about OOP, and I was wondering if I could get a revision of my code, and maybe get some editing suggestions in case it doesn't match the UML.

Any help would be appreciated!
Uml

The code

public class Engine {
    private Integer weight;
    private Integer power;


    public Engine(Integer weight, Integer power) {
        this.weight = weight;
        this.power = power;
    }

    public Integer getWeight() {
        return weight;
    }

    public Integer getPower() {
        return power;
    }


}


import java.util.ArrayList;

public class Train {
    private Engine isTowedBy;

    private ArrayList consistsOf;

    public Train(Engine engine)
    {
        this.isTowedBy = engine;
        this.consistsOf = new ArrayList<>();


    }

    private Integer totalWeight()
    {
      return isTowedBy.getWeight();
    }

    public void addCoach(Coach coach)
    {
        consistsOf.add(coach);
    }

    public Integer totalCapacity()
    {
        return consistsOf.size();
    }


}

public class Coach {
    private Integer weight;
    private Integer capacity;

    private Train consistsOf;


    public Coach(Integer weight, Integer capacity) {
        this.weight = weight;
        this.capacity = capacity;
    }

    public Integer getWeight() {
        return weight;
    }

    public Integer getCapacity() {
        return capacity;
    }


}

```

Object-oriented – A URL shortener in memory in Java

This is a popular question in machine coding rounds. The requirements are to build a URL shortener. There are certain registered users who have the ability to define a URL and an optional time to live. The system generates a shortened URL. Unregistered users can also generate a shortened URL with a predefined TTL. This is the URLshortener class.

package urlshortener;

import hashalgorithm.IHashStrategy;

import java.util.*;

public class UrlShortener {
    private IHashStrategy iHashStrategy;
    private Map> userToUrl;
    private List registeredUser;
    static final int DEFAULT_TIME_TO_LIVE_IN_MILLIS = 500000;
    public UrlShortener(IHashStrategy instanceOfConcreteHashStrategy) {
        iHashStrategy = instanceOfConcreteHashStrategy;
        userToUrl = new HashMap<>();
        registeredUser = new ArrayList<>();
        registeredUser.add("abc");
        registeredUser.add("bad");
        registeredUser.add("bac");
        registeredUser.add("lom");
        registeredUser.add("DEFAULT");
    }

    public List getListOfShortenedUrlForUser(String userId) {
        List urlList = getUrls(userId);
        userToUrl.put(userId,urlList);
        return urlList;
    }

    public void addNewEntryForUser(String url,String userId) {
       addNewEntryForUserWithTTL(url,userId,DEFAULT_TIME_TO_LIVE_IN_MILLIS);
    }

    private boolean checkExistenceForShortenedUrl(String shortenedUrl) {
        for(Map.Entry> entry : userToUrl.entrySet()) {
            List urlList = entry.getValue();
            for(int i = 0 ; i < urlList.size() ; i++) {
                if(urlList.get(i).getShortenedUrl().equalsIgnoreCase(shortenedUrl))
                    return true;
            }
        }
        return false;
    }

    public void addNewEntryForUserWithTTL(String url,String userId,int timeToLive) {
        if(!registeredUser.contains(userId)) {
            System.out.println("userId is not registered. Treated as default!");
            userId = "DEFAULT";
        }
        List urlList = userToUrl.get(userId);
        String shortenedUrl = iHashStrategy.getHashFromUrl(url);
        while(checkExistenceForShortenedUrl(shortenedUrl)) {
            shortenedUrl = iHashStrategy.getHashFromUrl(url);
        }
        System.out.println(shortenedUrl);
        Url urlToInsert = new Url(url,shortenedUrl,timeToLive,new Date());
        if(urlList == null)
            urlList = new ArrayList<>();
        urlList.add(urlToInsert);
        userToUrl.put(userId,urlList);
    }

    public String getShortenedUrlForUser(String url,String userId) {
        if(!registeredUser.contains(userId)) {
            System.out.println("userId is not registered. Treated as default!");
            userId = "DEFAULT";
        }
        List urlList = getUrls(userId);
        for(int i = 0 ; i < urlList.size(); i++) {
            if(urlList.get(i).getOriginalUrl().equalsIgnoreCase(url))
                return urlList.get(i).getShortenedUrl();
        }
        return null;
    }

    private List getUrls(String userId) {
        List urlList = userToUrl.get(userId);
        for (int i = 0; i < urlList.size(); i++) {
            Url currentUrl = urlList.get(i);
            if (!currentUrl.isValid()) {
                urlList.remove(i);
            }
        }
        return urlList;
    }

    public String getLongUrlForUser(String shortUrl,String userId) {
        List urlList = getUrls(userId);
        for(int i = 0 ; i < urlList.size(); i++) {
            if(urlList.get(i).getShortenedUrl().equalsIgnoreCase(shortUrl));
                return urlList.get(i).getOriginalUrl();
        }
        return null;
    }

}

And this is URL.java

package urlshortener;

import java.util.Date;

public class Url {
    private String originalUrl;
    private String shortenedUrl;
    private int timeToLive;
    private Date date;

    public Url(String originalUrl, String shortenedUrl, int timeToLive, Date date) {
        this.setShortenedUrl(shortenedUrl);
        this.setTimeToLive(timeToLive);
        this.setOriginalUrl(originalUrl);
        this.setDate(date);
    }

    public boolean isValid() {
        Date timeNow = new Date();
        Date expireDate = new Date(this.getDate().getTime() + getTimeToLive());
        return timeNow.before(expireDate);
    }

    public String getOriginalUrl() {
        return originalUrl;
    }

    public void setOriginalUrl(String originalUrl) {
        this.originalUrl = originalUrl;
    }

    public String getShortenedUrl() {
        return shortenedUrl;
    }

    public void setShortenedUrl(String shortenedUrl) {
        this.shortenedUrl = shortenedUrl;
    }

    public int getTimeToLive() {
        return timeToLive;
    }

    public void setTimeToLive(int timeToLive) {
        this.timeToLive = timeToLive;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}

For the rest of the code, see https://github.com/suryasis-hub/urlshortener/tree/master/src

object-oriented: generic heap implementation in C #

This has already been done a thousand times here, but here is another implementation of binary heap. The implementation is generic in terms of dynamic storage elements, allows the injection of any type of comparison strategy through the constructor and has an additional internal search scheme to achieve the elimination of elements in time O (log (n)) .

I am looking for general advice to better use language (C #), design ideas to improve the structure / performance of this class or any other comments. Thank you!

using System;
using System.Collections.Generic;
using System.Linq;

namespace GenericHeap
{
    /// 
    /// A generic heap implementation that allows injection of custom comparison strategies for 
    /// determining element priority
    /// 
    /// Type of element that will be stored in the heap
    public class Heap where T : IComparable
    {
        /// 
        /// The heap's internal elements
        /// 
        protected readonly List elements;

        /// 
        /// A lookup for mapping each heap element value/instance to one or more indices in the internal array
        /// 
        protected readonly Dictionary> elementIndexLookup;

        private readonly IComparer comparer;

        /// 
        /// Returns true if there are no elements in the heap, otherwise returns false
        /// 
        public bool IsEmpty => elements.Count == 0;

        /// 
        /// Returns the number of elements in the heap
        /// 
        public int Count => elements.Count;

        /// 
        /// Constructs a  with default comparer for type 
        /// 
        public Heap() : this(Comparer.Default)
        {
        }

        /// 
        /// Constructs a  with custom comparer for type 
        /// 
        /// The custom comparer to use when determining priority order
        public Heap(IComparer comparer)
        {
            this.comparer = comparer;
            this.elements = new List();
            this.elementIndexLookup = new Dictionary>();
        }

        /// 
        /// Removes the highest priority element from the heap and returns it to the caller of 
        /// 
        /// The highest priority element
        /// Thrown when there are no elements in the heap
        public T Poll()
        {
            if (this.IsEmpty)
            {
                throw new InvalidOperationException("There are no elements in the heap to poll");
            }

            var rootIndex = 0;
            var lastElementIndex = this.elements.Count - 1;
            var root = this.elements(rootIndex);

            this.elements(rootIndex) = this.elements(lastElementIndex);
            this.elements.RemoveAt(lastElementIndex);

            this.BubbleDown(rootIndex);

            return root;
        }

        /// 
        /// Inserts an element into the heap
        /// 
        /// The element to insert
        public void Insert(T newElement)
        {
            this.elements.Add(newElement);
            var lastIndex = this.elements.Count - 1;
            this.AddIndexToLookup(newElement, lastIndex);

            this.BubbleUp(this.elements.Count - 1);
        }

        /// 
        /// Gets the highest priority element from the heap without removing it
        /// 
        /// The highest priority element
        /// Thrown when there are no elements in the heap
        public T Peek()
        {
            if (this.IsEmpty)
            {
                throw new InvalidOperationException("There are no elements in the heap to peek");
            }

            return this.elements(0);
        }

        /// 
        /// Checks if an element exists in the heap
        /// 
        /// The element to search for
        /// True if element exists in the heap, otherwise false
        /// 
        /// This method is an O(1) operation due to the usage of an internal element lookup
        /// 
        public bool Contains(T element)
        {
            return this.elementIndexLookup.ContainsKey(element);
        }

        /// 
        /// Removes the first instance of  found in the heap
        /// 
        /// The element to remove from the heap
        /// 
        /// This method is an O(log(n)) operation due to the usage of an internal lookup for
        /// identifying element indices
        /// 
        /// Thrown when  does not exist in the heap
        public void Remove(T elementToRemove)
        {
            if (!this.elementIndexLookup.ContainsKey(elementToRemove))
            {
                throw new ArgumentException("Element does not exist in the heap");
            }

            var index = this.elementIndexLookup(elementToRemove).First();
            var lastIndex = this.elements.Count - 1;

            this.SwapElements(index, lastIndex);
            this.RemoveIndexFromLookup(this.elements(lastIndex), lastIndex);
            this.elements.RemoveAt(lastIndex);
            this.BubbleDown(index);
        }

        private void BubbleDown(int parentIndex)
        {
            var leftChildIndex = this.GetIndexOfLeftChild(parentIndex);
            var rightChildIndex = this.GetIndexOfRightChild(parentIndex);
            var maxIndex = this.elements.Count - 1;

            if (leftChildIndex > maxIndex)
            {
                return;
            }

            if (rightChildIndex > maxIndex)
            {
                if (this.IsChildHigherPriority(parentIndex, leftChildIndex))
                {
                    this.SwapElements(parentIndex, leftChildIndex);
                }

                return;
            }

            var highestPriorityElementIndex = this.GetHighestPriorityElementIndex(parentIndex, leftChildIndex, rightChildIndex);

            if (highestPriorityElementIndex == parentIndex)
            {
                return;
            }

            this.SwapElements(parentIndex, highestPriorityElementIndex);
            this.BubbleDown(highestPriorityElementIndex);
        }

        private void BubbleUp(int childIndex)
        {
            if (childIndex == 0)
            {
                return;
            }

            var parentIndex = this.GetParentIndex(childIndex);

            if (IsChildHigherPriority(parentIndex, childIndex))
            {
                this.SwapElements(parentIndex, childIndex);
                this.BubbleUp(parentIndex);
            }
        }

        private bool IsChildHigherPriority(int parentIndex, int childIndex)
        {
            return this.comparer.Compare(this.elements(childIndex), this.elements(parentIndex)) > 0;
        }

        private int GetHighestPriorityElementIndex(int parentIndex, int leftChildIndex, int rightChildIndex)
        {
            var isLeftChildHigherPriority = this.IsChildHigherPriority(parentIndex, leftChildIndex);
            var isRightChildHigherPriority = this.IsChildHigherPriority(parentIndex, rightChildIndex);

            if (isLeftChildHigherPriority && isRightChildHigherPriority)
            {
                return this.GetHigherPriorityElementIndex(leftChildIndex, rightChildIndex);
            }
            else if (isLeftChildHigherPriority)
            {
                return leftChildIndex;
            }
            else if (isRightChildHigherPriority)
            {
                return rightChildIndex;
            }

            return parentIndex;
        }

        private int GetHigherPriorityElementIndex(int leftElementIndex, int rightElementIndex)
        {
            if (this.comparer.Compare(this.elements(leftElementIndex), this.elements(rightElementIndex)) > 0)
            {
                return leftElementIndex;
            }
            else
            {
                return rightElementIndex;
            }
        }

        private void SwapElements(int firstIndex, int secondIndex)
        {
            if (firstIndex == secondIndex)
            {
                return;
            }

            var firstElement = this.elements(firstIndex);
            var secondElement = this.elements(secondIndex);
            this.elements(firstIndex) = secondElement;
            this.elements(secondIndex) = firstElement;

            this.RemoveIndexFromLookup(firstElement, firstIndex);
            this.RemoveIndexFromLookup(secondElement, secondIndex);

            this.AddIndexToLookup(this.elements(firstIndex), firstIndex);
            this.AddIndexToLookup(this.elements(secondIndex), secondIndex);
        }

        private void RemoveIndexFromLookup(T element, int index)
        {
            this.elementIndexLookup(element).Remove(index);
        }

        private void AddIndexToLookup(T element, int index)
        {
            if (this.elementIndexLookup.ContainsKey(element))
            {
                this.elementIndexLookup(element).Add(index);
            }
            else
            {
                this.elementIndexLookup.Add(element, new HashSet { index });
            }
        }

        private int GetParentIndex(int childIndex)
        {
            if (childIndex % 2 == 0)
            {
                return (childIndex - 2) / 2;
            }
            else
            {
                return (childIndex - 1) / 2;
            }
        }

        private int GetIndexOfLeftChild(int currentIndex)
        {
            return 2 * currentIndex + 1;
        }

        private int GetIndexOfRightChild(int currentIndex)
        {
            return 2 * currentIndex + 2;
        }
    }
}
```

design patterns – Mathematical / computer examples for inheritance in object-oriented programming

I am fed up with all examples of Animal, Person (Employee, Worker, Personnel) and Vehicle inheritance. Can anyone provide an example of inheritance that is more mathematical / informatic by nature? I've been searching the Internet and the best I could find are examples of Shape. One of my examples are in fact Cuboid extends Rectangle. (I know there is also some design smell, I have overridden the method of the area of Rectangle to return the surface area of Cuboid. Hopefully it does not violate the LSP).

I know there is a similar question answered here on StackOverflow. I liked him Stream example and expression there but I really don't have an idea how to create a Stream class. I am looking for an example oriented to mathematical or data structures (not necessarily, I'm fine with any practical example) I realized that in the case of linked lists, neither List can inherit Node because that is clearly composition neither can DoublyLinkedList inherit from SinglyLinkedList.

Any help would be really appreciated!

Object-oriented design: heritage and composition combined

Let's say you have a wireless network that acts as a wireless bridge / repeater. How would both be factored in a class diagram? In my opinion, it makes sense to have a parent object that can exist on its own. Then, the child object that depends on the father, but also creates an instance of the father. The secondary element can access all inherited attributes, while it can overload the methods that use the methods and attributes of the main instance.

Does this make any sense about what I am trying to do? I am trying to combine composition with inheritance and I am not sure if that is the

In my opinion, a wireless repeater has a primary (aggregate) wireless network, but it also has a completely separate network that inherits the attributes of the wireless network. I want that address because the bridge network is a private extension of the main wireless network and needs to be able to show this in a sequence diagram.

Object-oriented: when is it appropriate to introduce a new abstraction layer in a class hierarchy?

Suppose I am creating a game played on a 2D coordinate grid. The game has 3 types of enemies that move in different ways:

  • Drunkard: moves using type 1.
  • Mummy: moves using type 1 movement, except when it is close to the main character, in which you will use type 2 movement.
  • Ninja: moves using type 3 movement.

These are the ideas that came to mind when organizing the class hierarchy:

Proposal 1

A single base class from where each enemy derives from:

abstract class Enemy:
    public show()   // Called each game tick
    public update() // Called each game tick
    abstract move() // Called in update

class Drunkard extends Enemy:
    private move() // Type 1 movement

class Mummy extends Enemy:
    private move() // Type 1 + type 2 movement

class Ninja extends Enemy:
    private move() // Type 3 movement

Problems:

  • Viola DRY since the code is not shared between Drunkard Y Mummy.

Proposal 2

Same as proposal 1 but Enemy does more:

abstract class Enemy:
    public show()            // Called each game tick
    public update()          // Called each game tick
    private move()           // Tries alternateMove, if unsuccessful, perform type 1 movement
    abstract alternateMove() // Returns a boolean

class Drunkard extends Enemy:
    private alternateMove(): return False

class Mummy extends Enemy:
    private alternateMove() // Type 2 movement if in range, otherwise return false

class Ninja extends Enemy:
    private alternateMove() // Type 3 movement and return true

Problems:

  • Ninja It doesn't really just have one movement, so it doesn't really have an "alternative movement." So, Enemy It is a poor representation of all enemies.

Proposal 3

Expanding proposal 2 with a MovementPlanEnemy.

abstract class Enemy:
    public show()   // Called each game tick
    public update() // Called each game tick
    abstract move() // Called in update

class MovementPlanEnemy:
    private move() // Type 1 movement
    abstract alternateMove()

class Drunkard:
    private alternateMove() // Return false

class Mummy:
    private alternateMove() // Tries type 2 movement

class Ninja:
    private move() // Type 3 movement

Problems:

  • Ugly and possibly oversized.

Question

Proposition 1 is simple but has a lower level of abstraction. Proposition 3 is complex but has a higher level of abstraction.

I understand all about the "composition about inheritance" and how it can solve this whole disaster. However, I have to implement this for a school project that requires us to use inheritance. So, given this restriction, what would be the best way to organize this class hierarchy? Is this just an example of why inheritance is inherently bad?

I guess since my restriction is that I have to use inheritance, I'm really asking the broader question: In general, when is it appropriate to introduce a new abstraction layer at the expense of complicating the architecture of the program?

Edit: updated title.

Add objects in object-oriented programming

Hello everyone, I have the following code, which has an instance method, which will have two parameters (in addition to self), which will be used to modify the properties (x, y) of the self object (the first parameter will be added to the value of the attribute "x" and the second to the property "y")

p = suma_Poo(2.3, 6.9)
p.suma(1.0, -1.0)
print("(x = {}, y = {})".format(p.x, p.y)) # Muestra "x = 3.3, y = 5.9"


class Point:

    def __init__(self, x, y):
"""La clase cuenta con dos atributos, 'x' e 'y'"""
       self.x = x
       self.y = y

     def suma_Poo(self, v1, v2):
        sumax = v1._x + v2_x
        sumay = v1._y + v2._y
        return (sumax, sumay)

if __name__ == "__main__":

# Example
  p = suma_Poo(2.3, 6.9)
  p.suma(1.0, -1.0)
  print("(x = {}, y = {})".format(p.x, p.y)) # Muestra "x = 3.3, y = 5.9"

object-oriented – OOP paradigm in python – Extend class functionalities

I am a newbie in Python and I am trying to understand how to use the OOP paradigm to improve my scripts. My scripts generally read some data from a formatted csv file and perform some numerical analyzes. Here is a brief example:

SIMPLY SUPPORTED BEAM 
NNODES 
2
1,0,0
2,1,0

This entry is for a script to solve a structural analysis problem. In general, you may want to extend the functionality of the script by adding new features, for example, adding elements, materials, section properties, etc.

My idea is to configure the code in such a way that one can include these functionalities in the easiest possible way.

My solution is to create a class and then extend it using inheritance. Here what I wrote so far:

  • A class for problem properties, called Mesh
  • Two initial instance variables that store the name of the input file and the title (first row of the csv file)
  • A method to read information from the file, called read_input
class Mesh() :
    'class defining the property of the problem'

    def __init__(self) :
        self.name = None
        self.title = None

    def read_input(self, input_name) :
        self.name = input_name
        with open(self.name) as file :
            self.title = file.readline()

Let's say that one may want to improve the script by including the number of nodes (NODES in the csv file). First I create a class for the node, storing ID and coordinates:

class Node() :
    'class for defining a node'

    def __init__(self, input1 , input2 , input3) :
        self.ID = int(input1)
        self.x = float(input2)
        self.y = float(input3)

Then I add "functionalities" to the class that defines a new secondary class (with the same name of the primary class, because I don't really need a new secondary class, just a redefinition of the initial Mesh class). The new class says:

  • New constructor, using super () to include the constructor of the main class and the new instance variables.
  • Redefinition of the read_input method to include the new lines of the csv file.
class Mesh(Mesh) :
    'Mesh that includes nodal loads'

    def __init__ (self) :
        super().__init__()
        self.Nnodes = None
        self.nodes = list()

    def read_input(self, input_name) :
        super().read_input(input_name)
        with open(self.name) as file :
            while not file.readline().startswith('NNODES') : continue
            self.Nnodes = int( file.readline() )
            for node in range(0,self.Nnodes) :
                ID , x, y = file.readline().split(',')
                self.nodes.append( Node( ID , x, y ) )

Finally, the initialization of the class and the use of the method to read the file:

input = Mesh()
input.read_input('input_short.txt')

Here my doubts:

  • Is it a good application of the OOP paradigm or have I completely misunderstood the concept?
  • Does it make any sense to call the secondary class with the same name as the primary class? (I didn't find any example in previous questions)
  • Is it a good way to structure the code? Maybe other people than me will modify the code in the future, and I would like to simplify this procedure as much as possible.

I have always used procedural languages, such as C and FORTRAN, and I have no experience in the OOP paradigm.

EDIT
I modified the code with StackOverflow suggestions

  1. Modification of the class. Mesh, in this way, it must be autonomous.
  2. Class name son different from father.
  3. Use of the data class to define the Node class.

Code:

from dataclasses import dataclass

class Mesh() :
    'class defining the property of the problem'

    def __init__(self , input1) :
        self.title = input1

name = 'input_short.txt'''
with open(name) as file :
    mesh1 = Mesh( file.readline() )

#let's add a new functionality
@dataclass
class Node:
    'class for defining a node'

    ID: int
    x: float
    y: float


class Mesh_nodes(Mesh) :
    'Extend Mesh class to account for nodes'

    def __init__(self , input1, input2, input3) :
        super().__init__(input1)
        self.Nnodes = input2
        self.nodes = input3

name = 'input_short.txt'''
with open(name) as file :
    while not file.readline().startswith('NNODES') : continue
    Nnodes = int( file.readline() )
    nodes = list()
    for node in range(0,Nnodes) :
        ID , x, y = file.readline().split(',')
        nodes.append( Node( int(ID) , float(x), float(y) ) )

mesh1 = Mesh_nodes(name,Nnodes,nodes)

Anyway, my original questions are still valid:

  • Is it a good application of the OOP paradigm or have I completely misunderstood the concept?

  • Is it a good way to structure the code? Maybe other people than me will modify the code in the future, and I would like to simplify this procedure as much as possible.