Account acct = (Account)myGenericSObject; is indeed correct here.
A more complete example would be something like this
// This uses implicit typecasting to turn the Account into an SObject (which
// works because Account extends/inherits from the SObject type) and we're
// traversing upwards in the type hierarchy (more specific type -> less specific
SObject myGenericSObject = new Account(Name = 'Trailhead');
// When using an SObject, we can really only access fields using .get()
// .get() returns a result of type 'Object', which we need to explicitly typecast
// (that's the "(String)" part of the line) to really be able to do anything with
acctName = (String)myGenericSObject.get('Name');
// There may be a few occasions where you can do implicit typecasting, but
// in general when you want to go from a generic type (e.g. SObject) to a more
// specific type (e.g. Account) you need to explicitly typecast
Account specificAccountObj = (Account)myGenericSObject;
// When you have a concrete/specific SObject (Account, Opportunity,
// My_Custom_Object__c, etc...), you can use dot notation to access fields
acctName = specificAccountObj.Name;
The implication here is that
myGenericSObject is currently being treated as a generic
SObject (but you want it to be an Account again).
Account acct = (Account)myGenericSObject; line basically says "yes, I know that myGenericSObject looks like an SObject, but trust me, it's really an Account, and store it in a variable of type Account".
In general, the type of the two sides of an expression have to match (or at least be compatible).
The left-hand side of that expression (
Account acct) dictates how the data can be used later on (i.e. it's a specific type of SObject, an
The right-hand side of that expression (
(Account)myGenericSObject) ensures that the resulting "type" of the expression matches that of the left-hand side.