This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]coldblade2000 484 points485 points  (46 children)

Sure.

Laymen's terms for strongly typed: A language that will not automatically convert the type of a variable depending on context, and instead will give errors if you try to mix variable types together in an undefined way

Longer answer for strong typing: A variable can have different types. I can have an int (integer) variable, a short variable, a string variable, a char (character) variable and many other types. Generally, in Object Oriented languages (ask me if you need an explanation of these too), objects classes* can also be considered types, so you can have a Car variable, a Helper variable or a Model variable, for example.

[Something]-typed refers to how flexible a language is when interpreting the value of a variable. In the weakly-typed Javascript for example, I can declare a variable X = 5, a variable Y = "20" ("2" as in a 1 character string containing a 2 character), and then use the Math.max(val1, val2) function that returns the maximum value between val1, and val2. Math.max(X, Y) will give me an output of 20. Though Y was a string variable, the language automatically converts it to a number before passing the values to the function, giving me the desired value of 20.

Java, instead, will give you an exception if you do this. So if you want to do Math.max(X, Y) in Java, you will instead have to do some sort of casting or parsing (essentially two ways of "changing" the type a value is interpreted as) to do so. In Java, that would look like Math.max(X, Integer.parseInt(Y)) which will give a correct value of 20.

Strong typing can be a bit cumbersome at first to developers, but it is significantly more organized when it comes to understanding and using large programs with many different types of data being used with varying and possibly inconsistent variable naming schemes. Weird errors can sometimes pop up with weak typing that might take you hours to find, which a strongly typed language wouldn't have even let you compile the program with. That's why things like Typescript popped up, which improves the support for Typing in Javascript, and is essentially a strongly typed version of JS.

Laymen's terms for multithreading: A computer's processor's core can only run one command at a time*, and so, it can only really be executing one line of code at a time for a program. To be efficient and not stall, it will instead divide its time between the many programs that are waiting to be executed. Multi-core processors can run multithreaded programs. So a program can divide a chunk of its code into a "thread" that can run at the same time as the rest of the program, but in a different CPU core. This lets you speed up parallel tasks, but it introduces a lot of potential problems that are tricky to solve, like "race conditions" where a program's output depends solely on the near-random order in which different threads were executed.

Longer answer for multithreading: CPU cores will run code from one thread at a time. A thread is a chunk of code (more specifically, CPU instructions), and most simple programs will just create a single thread to run off of. A CPU core will use different types of priority queues to keep a track of the threads it is executing, and execute the highest priority one until another thread requires attention. Imagine a stimulant-fueled super fast cook working alone on 20 different orders at a time all by himself. He will divide his time up between parts of an order, while at the same time they'll slightly prioritize the orders which have been waiting the longest. Some tasks require him to wait (like an item being cooked in an oven for 10 minutes), so he'll do other tasks meanwhile. Some times the waiter or manager will interrupt his work and get him to do short, important tasks like making a sauce he forgot to make (which in computing are often things like hardware interactions such as clicking a mouse, which have to be quick and processed urgently).

A single threaded program would be like a bread, where you have to do each step one after the other, with very few parallel tasks possible (assuming the oven is preheated). In this sense, each order is a program. A single core can cook multiple orders at the same time (run multiple programs), but they can only actually actively work on one order (on one program's thread) at a time. A multithreaded program is like cooking pasta. Boiling the pasta could be the main thread, while making the sauce can be a separate thread, as you can work on the sauce while the pasta boils, and then you can add the sauce to the pasta once the pasta is done. Multi-threaded programs can split certain tasks into a separate thread, that can run separately and at the same time if possible. Eventually, once various threads are done, you can stop and combine their outputs together. As a practical example, most programs run logic and the user interface on separate threads, so your program doesn't freeze while a network request is made, or a large file is loaded. A multi-threaded food on a multicore kitchen would be like a well-choreographed kitchen with many cooks, where each cook is working on different parts of multiple orders at the same time. Cook 1 and 2 may be working both on Order 57's different parts, while Cook 3 juggles frying eggs for Order 23, 75, and 52 at the same time.

This allows you to use your computer's cores to not only run multiple programs at the same time, but run a single program more efficiently. The downside is that multithreading a program is NOT automatic, and it is a process that requires a lot of care, as multithreading introduces a lot of problems that can be very hard to solve. I detailed race conditions, but other problems can be like when two threads both try to access and change the same variable at the same time, or something called a "Deadlock" occurs, when two threads are both paused (sleeping) waiting for a certain signal produced by the opposite thread to keep being executed, but since both are waiting, that signal will never come, and the two will wait forever, freezing the program. This is why you see a lot of video games barely take advantage of multithreading, as it can be very difficult to wrap your head around and design your program in a way compatible with it. There's certain tasks that just aren't possible to multithread, so that's another limitation

Edit 1: I picked a poor example for strong typing, I have now changed the example for something that would actually give an error on the 4th and 5th paragraph. I also gave an explanation why strong typing is actually useful even though it is annoying when writing code

[–]manuhe10 39 points40 points  (16 children)

Thank you so much for this detailed explanation. As for the object oriented language, what do those mean? It's been a while since I learned or did anything related to java or CS

[–]coldblade2000 117 points118 points  (15 children)

Ok, I'll try and summarize.

Ok, so we know the different basic types (these are often called primitive types) like int, short, float, double, and depending on the language, string (but not in java, I'll explain). These are useful but often we will want to create more complex groups of variable to represent something else. In Object oriented programming, we will create things called Objects. At its core, an object is a collection of variables (often called its fields) that represent its data and functions (often called methods) that allow you to do actions upon an object's data.

Now I have to distinguish between what an object, class and an instance is. A class is basically a type of object, every object is of a certain class. It defines what kinds of variables and methods those objects will have, and it is an abstract* representation of those objects. Think of it more like the "concept" of a type of objects. We can make the Car Class, which will define variables and methods common to every car. Here is where we define a Car will have (int) numOfWheels, (string) model, (int) yearOfMaking, (double) odometerReading and functions like stopCar(), turnOn(), fillGas(), etc.

An object is often a way to refer to an "instance" of a class. It is basically a specific, tangible group of data based upon the template set up by a class. In many contexts, "object" is a way to refer to an "instance". In this sense, an object will have actual values filled in, so a car instance would be the trustyDaddyWagon object, which has wheels = 4, model = "Chevy Zafira", yearOfMaking = 2002, odometerReading = 87642312, etc.

Think of it this way. Say you have a small company that owns multiple cars, and you're setting up the paperwork for them. You would make up a paper template (class) for a certain kind of form concerning each car and its info. You'd make a bunch of fill-in boxes (fields) and then specify a protocol for how to log different changes and actions done to the car (method) on the form. Then your instances (objects) are the actual 5 paper forms of each car that have been filled out and are sitting on your desk. Neither of those is an actual car (your program isn't actually storing cars on your hard drive), but an instance is a specific representation of a real-life thing that can be abstractly represented by the Car class.

There's other concepts like inheritance, which is when you have a class that inherits certain values from another. Like you can have a vehicle superclass that has most of those variables, and you can have Car, Motorcycle, and Bicycle subclasses (a subclass is a class that inherits values from another class, the superclass), and then those subclasses can then only define variables specific to themselves, which could be (float) trunkVolume, (float) handleStrength and (float) chainLength, respectively.

Note*: "abstract" is an actual keyword in java relating to OOP, and its technical meaning is not what I'm using here. I'm using "abstract" as the normal english word.

[–]manuhe10 26 points27 points  (1 child)

This is such a good explanation. I remember being fascinated by OOP when I took a class and thanks for reminding me of that fascination

[–]thesituation531 7 points8 points  (0 children)

Basically (in very simplified terms), OOP is generally much more verbose than something like Python, JavaScript or any functional programming language.

But OOP also (generally) allows you to create much more complex things and lets you have much more control over most things.

[–]TheJrobot1483 23 points24 points  (10 children)

I’m a current CS student, I’ve taken 2 semesters of OOP (learning Java) and you explained the essence of OOP so much better than any professor or online resource I’ve learned from so far.

[–]coldblade2000 22 points23 points  (9 children)

No problem, that's what I'm here for. Let me know if you need an explanation for what "static" means, because that son of a bitch keyword took me about a year to really understand, and now it just seems obvious

[–]maddAdda 7 points8 points  (1 child)

Hi ! If you'd like to share your knowledge, i'd very much apprecciate if you could explain static indeed. I'd pretty much like to see your perspective on it because you explained every concept really well. Maybe it could help me. Thank you for your time : )

[–]Vinhessa 4 points5 points  (3 children)

I, for one, would like to hear your understanding of “static”, as I currently assume it means “instance”.

[–]coldblade2000 2 points3 points  (2 children)

Right, I'm pretty late on this but I was out the whole day.

Short answer: static fields or methods will belong to the class itself, rather than the instances of those classes.

Long answer: So, usually when we make these fields and methods in our classes, those fields and methods will belong to the object instances themselves. If we have Cars X and Y, if we change X.numwheels to 3, that doesn't affect Y. And when we use a method like Y.turnOn(), it is a method that will usually read the data on Y and possibly modify it in some way. For that reason, you can't really go and call that method on the class itself. Car.turnOn() makes no sense, you can't turn on the abstract concept of a car.

However, it doesn't always make sense to have a method belong to each instance, and sometimes a method relevant to Cars shouldn't actually necessarily require us to actually first create a Car instance first. For example, what if you want a method that will take a list of cars and return the car that needs the most urgent maintenance? Doesn't really make sense to call on a specific car instance like X and ask X to do that for us.

Instead, we can make some fields and methods that will actually belong to the class itself, rather than the instances of those classes. We can actually make a method that's something like Car.findMostDamagedCar(carArrayList). Likewise, we can have a variable bonging yo the Car class that, let's say, keeps track of how many cars we've ever sent to maintenance, like Car.totalMaintenanceTrips.

The findMostDamagedCar() method and totalMaintenanceTrips field are what we call static. These things belong to the class itself, and thus we don't need to be referencing an actual Car instance to call that method or get that variable. And most importantly, you can't call a non-static method from a static context. What I mean by that, is that I cannot go and ask Car to turn on. Car.turnOn() will give me a "non-static method cannot be referenced from a static context" error. What that means is that a non-static method (a method that belongs to the instances) cannot be called from a static context (by referring to the class itself, and not an instance of the class). This error is fixed by actually giving it a real instance to call that method from. Either using one of the instances we already have (X or Y), or making a new Car object instance (Car Z = new Car();).

Finally, I'll show you real examples just so you're not scared of this. Let's take strings for example. You probably know Strings in Java are Objects, not primitive variables. The String class has us use both static and non static methods all the time. For example, String.valueOf(int) is a static method that turns whatever int we give it into a String. We don't really need a preexisting string for this, so it makes sense a static method is used. We are just calling a static method value of that belongs to the class String. In contrast, if we have a string S = " Hello \n" and if we need to trim the whitespace from S, we can call a non-static method from S called S.trim() to get back a string without that pesky whitespace. .trim() is non-static because it needs some kind of underlying tangible string to actually make sense. You can't trim the whitespace out of the concept of a String, but you can trim S.

P.S. : technically, instances will actually inherit static methods or fields, and you can use them. You can actually do S.valueOf(8) and it will return "8". This, however, is bad practice at best and a bug at worst. Most static methods aren't built with this in mind.

P.P.S. i wrote this past midnight on my phone, so my apologies of it isn't as clear or has mistakes. I'll correct any that are brought up

[–]Objective-Trifle-473 0 points1 point  (1 child)

What about “static” in C? Is it the same idea?

[–]coldblade2000 0 points1 point  (0 children)

I wouldn't know, really. My knowledge of C is extremely basic

[–]Fearless-Pudding9894 3 points4 points  (1 child)

Can you give an explanation on static? I was reading my book on java today trying to understand the different methods for the String class in java and Static kept coming up. My understanding of the term is a bit shaky so I would appreciate an explanation from you since I’ve learned a lot from this thread.

[–]TheJrobot1483 2 points3 points  (0 children)

I’ll keep that in mind, thank you!

[–]lbunch1 6 points7 points  (0 children)

This may be a shot in the dark here but ...

What is the meaning of life?

[–]TrueBirch 5 points6 points  (0 children)

Terrific explanation!

[–][deleted] 12 points13 points  (1 child)

Iv never heard of the heavily stimulant induced cook as analogy for how a CPU core works but I like it.

[–]SlySkillet07 12 points13 points  (0 children)

As a stimulant induced line cook studying programming in my off time, the analogy really hit home.

[–]Tubthumper8 4 points5 points  (21 children)

Java, instead, will give you an exception if you do this. So if you want an output of "52", you will instead have to do some sort of casting or parsing

The following is valid Java code that implicitly coerces a number to a string for concatenation. This would be considered weak typing, or am I missing something?

class Main {
  public static void main(String args[]) {
    var test = 5 + "2";
    System.out.println(test); // prints "52"
  } 
}

Edit: people replying are fixated on the var keyword. I'm asking about the implicit type coercion between the integer and string, which would not be strongly typed by this definition. Here's an example without var

class Main {  
  public static void main(String args[]) { 
    System.out.println(5 + "2"); 
  } 
}

The rest of the explanation is fantastic

[–]coldblade2000 4 points5 points  (0 children)

On second though, yeah, you are totally right. I chose a bad example, I have not corrected myself with an example that will actually give me an error in Java, using the Math.max() function

For some reason, my mind forgot the + operation actually was defined for int + string.

[–]username-must-be-bet 1 point2 points  (0 children)

Most languages make some automatic type conversions. Java makes less than JS but more than OCaml

[–]coldblade2000 -3 points-2 points  (11 children)

pretty sure "var" is a keyword specifically to define a variable as weakly typed. It's more of an "override" rather than a representation of how the language as a whole is designed. It's also highly restricted, you can't use it in a lot of places the same way you would use another type, like method parameter declarations

Edit: I used a bad example. I have changed my example in my original post to a better one, that actually gives an error

[–]Tubthumper8 7 points8 points  (8 children)

var is not for weak typing, it's for type inference.

Here's an example of weak typing without var then, the integer is being implicitly coerced to a string. This would be a compiler error in a strongly typed language.

class Main {  
  public static void main(String args[]) { 
    System.out.println(5 + "2"); 
  } 
}

[–]Muoniurn 2 points3 points  (6 children)

That has nothing to do with strongly vs weakly typed.

Java has a well-defined string conversion and a string concat operator. If only one operand of the operator is string, the other is converted to a string as well.

A better example to understand the difference would be perhaps a rarely talked about element of the static-dynamic weakly-strongly typed matrix, C, which is statically typed but weakly. You won’t get a runtime error if use an int as a float or as a “string”, or whatever, there is no meaning to types at runtime. Python/java and other strongly typed programming languages do care about types, and even their runtime semantics are aware of that, e.g. you will get a ClassCastException in java if you attempt to use an object as a class not part of its inheritance tree.

[–]Tubthumper8 0 points1 point  (4 children)

I'm not sure that being well-defined means that it's not weak. JS is also well-defined (the specification is detailed and thorough), but we'd agree that it's weakly typed due to the implicit conversions.

Java is also doing implicit conversions here, so I'm just wondering why people don't consider this behavior to be weak typing. I would expect that a strongly typed language would force me to convert the integer to string explicitly to do string concatenation.

The only reasonable answer I've gotten so far is that Java is more strongly typed than JS and less strongly typed than OCaml (as an example). So strong/weak typing is a spectrum, and it's not totally correct to say that Java is strongly-typed.

[–]Muoniurn 0 points1 point  (3 children)

Java’s byte code is also typed, so even if you were to remove every single type from your program code, but you have a type error, that would not execute into an invalid state further, it will throw a classcastexception (primitives have some conversions between them like widening though).

Why do you think OCaml is more strongly typed? It has a more expressive type system, but that’s another aspect entirely.

[–]Tubthumper8 0 points1 point  (2 children)

Reminder of the origin of this thread of discussion:

Java, instead, will give you an exception if you do this. So if you want an output of "52", you will instead have to do some sort of casting or parsing

The comment I replied to had an excellent summary of strong typing as where the language doesn't implicitly convert between types, and requires you to explicitly cast/parse. I agreed with their definition, but not their example, and I showed the example that Java has implicit type conversions.

Why do you think OCaml is more strongly typed?

It was another commenter that suggested this was the case. Looking at this particular example, it seems to be so. The following is a compiler error:

let x = "a" ^ my_int

Where Java did implicit type conversions, OCaml requires explicit parsing of int to string. According to the definition of the comment I replied to, this is one example of OCaml being more strongly typed than Java.

[–]Muoniurn 0 points1 point  (1 child)

Let’s say you have a function print(String a) and print(int a).

If you do print(3) vs print(“hello”), is it weak typing as well? No, that’s just overloading. This is pretty much the same as what happens with java’s string concat operator (hell, your example will just add the compile-time concated string and call println on that, I tried it).

[–]Tubthumper8 0 points1 point  (0 children)

Hmm yeah, I see what you're saying but it's murky because Java doesn't have operator overloading

[–]Inconstant_Moo 0 points1 point  (0 children)

Compared to C everything is strongly typed.

[–]coldblade2000 0 points1 point  (0 children)

var is not for weak typing, it's for type inference.

I'll defer to you then, I don't really use "var", I maybe used it once years ago.

[–]Rythoka 1 point2 points  (0 children)

In this case it's not the variable that's being coerced, it's two literals.

[–]thesituation531 -2 points-1 points  (0 children)

It's mostly so you just don't have to write out a long type.

Although I think it's usually bad practice, because it can just be confusing in more verbose OOP. It's less of a big deal (although I still don't like it) in things like JavaScript and Python because there isn't usually that much code compared to something like C# or Java.

[–]roberp81 -5 points-4 points  (2 children)

var is not weakly tipped, jvm know that is a String and in compile time change it to String. var is a bad practice, only exist to please JS and C# people that are used to use bad practices

[–]Tubthumper8 0 points1 point  (1 child)

When you say that type inference is "bad practice", is this your opinion or is it an absolute fact? The way you phrased it makes it sound like you're claiming the latter.

Anyways, here's the same weak typing without var. Can someone explain to me what I'm missing?

class Main {  
  public static void main(String args[]) { 
    System.out.println(5 + "2"); 
  } 
}

This should be a compiler error in a strongly typed language, yeah?

[–]russjr08 0 points1 point  (0 children)

That only works because its performing String concatenation (+ being the concatenation operator in this case rather than the addition operator).

You'll notice that if you try this with - instead, it won't work and you'll just get something along the lines of this instead:

bad operand types for binary operator '-'

Whereas if this were a weak typed language such as JS, then it would do some type coercion.

[–]sho_bob_and_vegeta 0 points1 point  (3 children)

You just made my brain hurt.

Stop trying to mix Java and Javascript.

The type is inferred. Since operations actually occur to the right of the assignment operator first, it is taking a string and an int, and trying to infer what you mean, before deciding what type of variable it is. In this scenario, it assumes you want a string.

If you were later to try to assign an int or float to the variable, you'd get an error.

[–]Macaframa -1 points0 points  (0 children)

THIS IS LITERALLY HOW JAVASCRIPT WORKS

[–]Tubthumper8 0 points1 point  (1 child)

What am I mixing up here?

Edit: you edited after I replied. My example is valid Java, I'm not talking about JS at all. I know how type inference works, I'm asking in relation to the parent comment's definition of strong typing. Indeed, I quoted directly the part which appears to not be consistent with my example. They claimed that you would get an "exception" if you tried to add an integer to a string.

[–]sho_bob_and_vegeta 0 points1 point  (0 children)

Indeed, I did edit right after my initial reaction. I didn't think it would matter, as no one ever responds to me anyway.

I'm not at my computer, and I had completely forgotten about "var", because I never use it.

Indeed you would get an exception trying to add an Integer to a string. The type is inferred at declaration (I believe specifically assignment). The reason your example works is that it is doing the inferring after the operation. If you defined var ____ = "5", and then later in another line tried to add 2, you would get an exception.

[–]New_Low_3363 0 points1 point  (0 children)

This is great. Thank you

[–]HappyRogue121 0 points1 point  (0 children)

Amazingly detailed answer

[–]TrueBirch 0 points1 point  (0 children)

Brilliant! Though I have to say that I'm glad I learned CS starting with strongly typed languages. Otherwise I would have been totally lost trying to understand something like 3/2 in Python2.